【问题标题】:Load language specific string from resource?从资源中加载语言特定的字符串?
【发布时间】:2011-03-09 11:08:17
【问题描述】:

在我的一个 Android 应用程序中,有一次我需要加载特定语言的字符串。例如:

 values:    <string name="txt_help">Help</string>
 values-de: <string name="txt_help">Hilfe</string>
 values-fr: <string name="txt_help">Aider</string>

现在我需要默认(值)文本。

有没有办法用给定的语言“en”加载键“txt_help”?我找不到可以将语言环境设置为附加参数的方法。

或者我可以用给定的语言环境创建一个新的 ResourceManager 并通过这个资源对象读取字符串吗?

提前非常感谢。 hjw

【问题讨论】:

标签: android string resources


【解决方案1】:

查看the documentation,这看起来很有希望:

Resources standardResources = context.getResources();
AssetManager assets = standardResources.getAssets();
DisplayMetrics metrics = standardResources.getDisplayMetrics();
Configuration config = new Configuration(standardResources.getConfiguration());
config.locale = Locale.US;
Resources defaultResources = new Resources(assets, metrics, config);

换句话说,创建一个配置为标准语言环境的新资源对象。

【讨论】:

  • 非常接近......奇怪的是Resources defaultResources = new Resources(assets, metrics, config); 行似乎改变了一些东西,所以在调用之后,getResources() 返回我在这里自定义设置的新语言环境......任何线索为什么那会发生吗?我想我总是可以将 config.locale 重新设置回原来的;但我不明白创建一个新的 Resources 对象会如何导致我的标准 getResources() 发生变化。
  • @GendoIkari:看起来你是对的。问题是 Resources 对象在内部将其配置(包括语言环境)下推到底层 AssetManager 对象,因此两个 Resources 对象底层的 AssetManager 正在发生变化。不幸的是,似乎没有任何记录方法可以克隆或创建新的 AssetManager,只是为了检索现有的 AssetManager。所以看起来我们在获取资源之前更改配置,然后再将其更改回来。
  • 有趣...谢谢。我稍微弄乱了代码,所以现在我只调用new Resources(assets, metrics, config); 构造函数;甚至不需要将其设置为变量。我只是设置了配置;调用构造函数;拿到我的琴弦;然后重新设置配置并再次调用构造函数。有用。再次感谢!
  • @GendoIkari:就此而言,您可以在现有资源对象上调用updateConfiguration
  • @Anomie:你会这么认为的......只是测试了它;并得到了一些非常奇怪的行为。当我使用new Resources(assets, metrics, config); 设置配置时;有用。当我使用res.updateConfiguration(config, metrics); 时,应用程序冻结...不会崩溃;只是变暗;之后我可以点击“返回”,但所有显示都绘制不正确。
【解决方案2】:

my own question 参考this answerthis answer,我想出了以下自定义类解决方案:

package com.my.package.localisation;

import android.content.Context;
import android.content.res.AssetManager;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.os.Build;
import android.support.annotation.NonNull;
import android.util.DisplayMetrics;

import java.util.Formatter;
import java.util.Locale;

/**
 * Class to manage fetching {@link Resources} for a specific {@link Locale}. API levels less
 * than {@link Build.VERSION_CODES#JELLY_BEAN_MR1} require an ugly implementation.
 * <p/>
 * Subclass extends {@link Resources} in case of further functionality requirements.
 */
public class MyResources {

    private final Context mContext;
    private final AssetManager assetManager;
    private final DisplayMetrics metrics;
    private final Configuration configuration;
    private final Locale targetLocale;
    private final Locale defaultLocale;

    public MyResources(@NonNull final Context mContext, @NonNull final Locale defaultLocale,
                         @NonNull final Locale targetLocale) {

        this.mContext = mContext;
        final Resources resources = this.mContext.getResources();
        this.assetManager = resources.getAssets();
        this.metrics = resources.getDisplayMetrics();
        this.configuration = new Configuration(resources.getConfiguration());
        this.targetLocale = targetLocale;
        this.defaultLocale = defaultLocale;
    }

    public String[] getStringArray(final int resourceId) {

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
            configuration.setLocale(targetLocale);
            return mContext.createConfigurationContext(configuration).getResources().getStringArray(resourceId);
        } else {
            configuration.locale = targetLocale;
            final String[] resourceArray = new ResourceManager(assetManager, metrics, configuration).getStringArray(resourceId);
            configuration.locale = defaultLocale; // reset
            new ResourceManager(assetManager, metrics, configuration); // reset
            return resourceArray;
        }
    }

    public String getString(final int resourceId) {

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
            configuration.setLocale(targetLocale);
            return mContext.createConfigurationContext(configuration).getResources().getString(resourceId);
        } else {
            configuration.locale = targetLocale;
            final String resource = new ResourceManager(assetManager, metrics, configuration).getString(resourceId);
            configuration.locale = defaultLocale; // reset
            new ResourceManager(assetManager, metrics, configuration); // reset
            return resource;
        }
    }

    private final class ResourceManager extends Resources {
        public ResourceManager(final AssetManager assets, final DisplayMetrics metrics, final Configuration config) {
            super(assets, metrics, config);
        }

        /**
         * Return the string array associated with a particular resource ID.
         *
         * @param id The desired resource identifier, as generated by the aapt
         *           tool. This integer encodes the package, type, and resource
         *           entry. The value 0 is an invalid identifier.
         * @return The string array associated with the resource.
         * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
         */
        @Override
        public String[] getStringArray(final int id) throws NotFoundException {
            return super.getStringArray(id);
        }

        /**
         * Return the string value associated with a particular resource ID,
         * substituting the format arguments as defined in {@link Formatter}
         * and {@link String#format}. It will be stripped of any styled text
         * information.
         * {@more}
         *
         * @param id         The desired resource identifier, as generated by the aapt
         *                   tool. This integer encodes the package, type, and resource
         *                   entry. The value 0 is an invalid identifier.
         * @param formatArgs The format arguments that will be used for substitution.
         * @return String The string data associated with the resource,
         * stripped of styled text information.
         * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
         */
        @NonNull
        @Override
        public String getString(final int id, final Object... formatArgs) throws NotFoundException {
            return super.getString(id, formatArgs);
        }

        /**
         * Return the string value associated with a particular resource ID.  It
         * will be stripped of any styled text information.
         * {@more}
         *
         * @param id The desired resource identifier, as generated by the aapt
         *           tool. This integer encodes the package, type, and resource
         *           entry. The value 0 is an invalid identifier.
         * @return String The string data associated with the resource,
         * stripped of styled text information.
         * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
         */
        @NonNull
        @Override
        public String getString(final int id) throws NotFoundException {
            return super.getString(id);
        }
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-25
    • 1970-01-01
    相关资源
    最近更新 更多