使独立的第三方能够本地化Android应用程序;应用APK之外的本地化数据

使独立的第三方能够本地化Android应用程序;应用APK之外的本地化数据,第1张

概述我需要开发一个 Android应用程序,从其主要APK之外的外部资源加载本地化文本.这样做的原因是为了使第三方能够独立提供应用程序的翻译.该应用程序目前具有单个英语本地化,具有相当多的字符串(~2,000). 我宁愿不打破Android的资源系统;例如,我想在strings.xml中提供主要语言本地化字符串,就像在任何Android应用程序中一样. 为了实现这一点,我创建了一个扩展android. 我需要开发一个 Android应用程序,从其主要APK之外的外部资源加载本地化文本.这样做的原因是为了使第三方能够独立提供应用程序的翻译.该应用程序目前具有单个英语本地化,具有相当多的字符串(~2,000).

我宁愿不打破AndroID的资源系统;例如,我想在strings.xml中提供主要语言本地化字符串,就像在任何AndroID应用程序中一样.

为了实现这一点,我创建了一个扩展androID.content.res.Resources的类,重写了三个getText方法.覆盖实现将尽可能从外部本地化源返回资源,否则将请求转发给super.getText()实现.

资源包装器:

public class IntegratedResources extends Resources {    private ResourceIntegrator ri;    public IntegratedResources(AssetManager assets,displayMetrics metrics,Configuration config,ResourceIntegrator ri) {        super(assets,metrics,config);        this.ri = ri;    }    @OverrIDe    public CharSequence getText(int ID)            throws NotFoundException {        return ri == null ? super.getText(ID) : ri.getText(ID);    }    @OverrIDe    public CharSequence getText(int ID,CharSequence def)            throws NotFoundException {        return ri == null ? super.getText(ID,def) : ri.getText(ID,def);    }    @OverrIDe    public CharSequence[] getTextArray(int ID)             throws NotFoundException {        return ri == null ? super.getTextArray(ID) : ri.getTextArray(ID);    }}

然后我创建了一个Contextwrapper实现来包装Activity的上下文.上下文包装器的getResources()方法将返回上面的IntegratedResources对象.

Contextwrapper:

public class IntegratedResourceContext extends Contextwrapper {    private IntegratedResources integratedResources;    public IntegratedResourceContext(Activity activity,String packagename)     throws nameNotFoundException {        super(activity);        ResourceIntegrator ri = packagename == null ? null : new ResourceIntegrator(activity,packagename);        displayMetrics displayMetrics = new displayMetrics();        activity.getwindow().getwindowManager().getDefaultdisplay().getMetrics(displayMetrics);        integratedResources = new IntegratedResources(activity.getAssets(),displayMetrics,activity.getResources().getConfiguration(),ri);    }    @OverrIDe    public Resources getResources() {        return integratedResources;    }}

最后我们有了“ResourceIntegrator”类,它从指定的已安装的第三方本地化APK中选择资源.如果需要,可以创建不同的实现以从XML或属性文件中提取它们.

ResourceIntegrator:

public class ResourceIntegrator {    private Resources rBase;    private Resources rExternal;    private String externalPackagename;    private Map<Integer,Integer> baseIDToExternalID = new HashMap<Integer,Integer>();    public ResourceIntegrator(Context context,String externalPackagename)     throws nameNotFoundException {        super();        rBase = context.getResources();        this.externalPackagename = externalPackagename;        if (externalPackagename != null) {            PackageManager pm = context.getPackageManager();            rExternal = pm.getResourcesForApplication(externalPackagename);        }    }    public CharSequence getText(int ID,CharSequence def) {        if (rExternal == null) {            return rBase.getText(ID,def);        }        Integer externalID = baseIDToExternalID.get(ID);        if (externalID == null) {            // Not loaded yet.            externalID = loadExternal(ID);        }        if (externalID == 0) {            // Resource does not exist in external resources,return from base.            return rBase.getText(ID,def);        } else {            // Resource has a value in external resources,return it.            return rExternal.getText(externalID);        }    }    public CharSequence getText(int ID)    throws NotFoundException {        if (rExternal == null) {            return rBase.getText(ID);        }        Integer externalID = baseIDToExternalID.get(ID);        if (externalID == null) {            // Not loaded yet.            externalID = loadExternal(ID);        }        if (externalID == 0) {            // Resource does not exist in external resources,return from base.            return rBase.getText(ID);        } else {            // Resource has a value in external resources,return it.            return rExternal.getText(externalID);        }    }    public CharSequence[] getTextArray(int ID)    throws NotFoundException {        if (rExternal == null) {            return rBase.getTextArray(ID);        }        Integer externalID = baseIDToExternalID.get(ID);        if (externalID == null) {            // Not loaded yet.            externalID = loadExternal(ID);        }        if (externalID == 0) {            // Resource does not exist in external resources,return from base.            return rBase.getTextArray(ID);        } else {            // Resource has a value in external resources,return it.            return rExternal.getTextArray(externalID);        }    }    private int loadExternal(int baseID) {        int externalID;        try {            String entryname = rBase.getResourceEntryname(baseID);            String typename = rBase.getResourceTypename(baseID);            externalID = rExternal.getIDentifIEr(entryname,typename,externalPackagename);        } catch (NotFoundException ex) {            externalID = 0;        }        baseIDToExternalID.put(baseID,externalID);        return externalID;    }}

我对stackoverflow的问题是上面的实现是否是一个好主意,它是否正确使用API​​,以及它的设计是否能够面向未来的AndroID未知版本.我之前没有见过有人这样做过,而且似乎无法在文档或网络上找到解决此问题的任何内容.

允许独立第三方翻译的基本要求非常关键.目前在内部维护此应用程序的数十种翻译是不可行的,而且我没有能力审查用户提供的翻译质量.如果这个设计是一个非常糟糕的想法并且没有类似的替代方案可用,那么本地化可能必须在没有AndroID的资源管理系统的情况下完成.

如果这是一个好主意,请随意使用和改进上述代码.

解决方法

My question to stackoverflow is whether the above is a good IDea

如果它是一个完整的解决方案,我会感到震惊,因为你不能强迫AndroID使用你的自定义Contextwrapper.它应该适用于您手动调用getString(),getText()等的任何地方,但我不知道它如何在AndroID访问超出您的某个活动之外的那些资源的任何地方工作.有很多地方你不能自己调用​​getText()等,例如:

>主屏幕发射器
>“设置”中的应用信息
>最近的任务清单

此外,除非您打算永远不要添加新字符串,否则您将遇到永久版本问题.您无法强制第三方翻译支持新字符串,因此您最终会得到一个混合了翻译和非翻译字符串的应用程序.

whether it’s using the API properly

那似乎没问题.

whether its design is future-proof against the unkNown versions of AndroID of tomorrow

AndroID将访问资源本身的位置数量可能会增加而不是减少.

It is not currently feasible to internally maintain doZens of translations for this application,and I have no capability to vet user-provIDed translations for quality.

然后只支持您愿意自己管理的语言.首先,正如我已经指出的那样,我不会在几个方面看到这将是一个完整的解决方案.其次,你似乎认为你的方法会让你不会因为糟糕的翻译而受到指责,虽然它可能会减少你得到的责任,但它不会消除这种责任.在这方面我同意Squonk的观点.

我很钦佩你提供更多翻译的热情,但是,就个人而言,我不会走这条特定的道路.

总结

以上是内存溢出为你收集整理的使独立的第三方能够本地化Android应用程序;应用APK之外的本地化数据全部内容,希望文章能够帮你解决使独立的第三方能够本地化Android应用程序;应用APK之外的本地化数据所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/web/1126609.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2022-05-30
下一篇2022-05-30

发表评论

登录后才能评论

评论列表(0条)

    保存