android多国语言字符串翻译处理技巧

AI权益加码!Claude Code、Cursor等20+工具免费用! 购周边限时加赠Coding Plan Lite,畅享主流AI工具!学习进阶更高效! 阅读详情

问题描述:

    假设要对android中的字符中进行翻译, 可以选择导出英文字符串资源, 然后对照翻译, 如果字符串中包含特殊字符& < > " ',

    如: <string>  i have &amp; a apple</string>

    翻译人员会觉得很奇怪, 所以可以将这些特殊字符转换成对应的字符后导出,如& < > 等, 最后翻译好后, 再将那些字符转换回去,不转换会编译报错


解题思路:

     1.利用正则表达式,  以<>为模版, 将已经翻译好的字符串分离成2个列表,   一个放正常的tag,如<string>,  另一个放其他的字符串

     2.将需要转换的字符转换回去

     3.合并2个列表

  

具体代码如下:

    


    private String convert(String value) {
        String result = value;
        System.out.println("origin: " + value);
        Pattern pattern = Pattern.compile("\\<[\\s\\S]*?\\>");
        Matcher matcher = pattern.matcher(result);
        boolean match = false;
        ArrayList<Integer> indexList = new ArrayList<Integer>();
        ArrayList<String> strList = new ArrayList<String>();
        ArrayList<String> tagList = new ArrayList<String>();
        ArrayList<String> notagList = new ArrayList<String>();

        while (matcher.find()) {
            match = true;
            indexList.add(matcher.start());
            indexList.add(matcher.end());
            tagList.add(value.substring(matcher.start(), matcher.end()));
        }

        if (match) {
            strList.add(value.substring(0, indexList.get(0)));
            for (int i = 0; i < indexList.size(); i++) {
                if (i + 1 < indexList.size()) {
                    strList.add(value.substring(indexList.get(i),
                            indexList.get(i + 1)));
                }
            }
            strList.add(value.substring(indexList.get(indexList.size() - 1)));

            for (int i = 0; i < strList.size(); i++) {

                if (i % 2 == 0 || i == strList.size() - 1) {
                    notagList.add(strList.get(i));
                }
            }

            System.out.println("strList: " + strList.toString());

            System.out.println("before nottagList: " + notagList.toString());
            processNoTagList(notagList);
            System.out.println("after nottagList: " + notagList.toString());

            System.out.println("before tagList: " + tagList.toString());

            ArrayList<String> processedTagList = new ArrayList<String>();

            if(tagList.size() > 2) {
                ArrayList<Integer> spliteIndexList = splitTagList(tagList);
                System.out.println("tagList: " + tagList.toString());

                for(int i = 0; i < spliteIndexList.size(); i = i + 2) {
                    int firstIndex = spliteIndexList.get(i);
                    int secondIndex = spliteIndexList.get(i + 1);
                    ArrayList<String> subTagList = new ArrayList<String>();
                    for(int j = firstIndex; j <= secondIndex; j++ ) {
                        subTagList.add(tagList.get(j));
                    }
                    System.out.println("i: " + i);
                    System.out.println("before subTagList: " + subTagList.toString());
                    processedTagList.addAll(processTagList(subTagList));
                }
            } else {
                processedTagList = processTagList(tagList);
            }

            //System.out.println("allTagList: " + allTagList.toString());

            if (strList.size() != processedTagList.size() + notagList.size()
                    && notagList.size() - processedTagList.size() != 1) {
                System.out
                        .println("error: "
                                + "strList size not equals processedTagList size plus notagList size");
            }

            System.out.println("begin mergerList: " + strList.toString());
            result = mergerList(processedTagList, notagList);

        } else {
            strList.add(value);
            processNoTagList(strList);
            result = strList.get(0);
        }

        System.out.println("result: " + result);
        System.out.println("------------------------------------------------------------------------------");

        return result;
    }

    private ArrayList<Integer> splitTagList(ArrayList<String> tagList) {
        ArrayList<Integer> spliteIndexList = new ArrayList<Integer> ();
        String firstTag = "";
        int theSameTag = 0;
        boolean updateFirstTag = true;

        for(int i = 0; i < tagList.size(); i++) {
            if(updateFirstTag) {
                firstTag = tagList.get(i).substring(0,tagList.get(i).replace(">", " ").indexOf(" ")) + ">";
                spliteIndexList.add(i);
            }

            if(i != 0 &&
                    updateFirstTag == false &&
                    (tagList.get(i).substring(0,tagList.get(i).replace(">", " ").indexOf(" ")) + ">")
                            .equals(firstTag)) {
                theSameTag++;

            }

            updateFirstTag = false;

            if(tagList.get(i).startsWith("</")
                    && ("<" +tagList.get(i).substring(2,tagList.get(i).length() -1) + ">").equals(firstTag)
                    && theSameTag == 0) {

                spliteIndexList.add(i);
                updateFirstTag = true;
            } else if(i != 0 &&
                    tagList.get(i).startsWith("</") &&
                    ("<" +tagList.get(i).substring(2,tagList.get(i).length() -1) + ">").equals(firstTag) &&
                    tagList.get(i).substring(2,tagList.get(i).length() -1)
                            .equals(tagList.get(i - 1).substring(1,tagList.get(i - 1).replace(">", " ").indexOf(" ")))) {
                theSameTag--;

            } else if(tagList.get(i).endsWith("/>") &&
                    (tagList.get(i).substring(0,tagList.get(i).replace(">", " ").indexOf(" ")) + ">").equals(firstTag)) {
                spliteIndexList.add(i);
                updateFirstTag = true;
            } else {
                continue;
            }
        }


        if(spliteIndexList.size() % 2 != 0) {
            spliteIndexList.add(tagList.size() - 1);
        }
        System.out.println("spliteIndexList: " + spliteIndexList);
        return spliteIndexList;
    }

    private String mergerList(ArrayList<String> tagList,
                                     ArrayList<String> notagList) {
        int index = 0;
        StringBuilder build = new StringBuilder();
        while (index < tagList.size()) {
            build.append(notagList.get(index) + tagList.get(index));
            index++;
        }
        build.append(notagList.get(index));

        return build.toString();
    }



    private ArrayList<String> processTagList(ArrayList<String> tagList) {
        ArrayList<String> pairTagList = new ArrayList<String>();
        ArrayList<Integer> pairTagListIndexInTaglist = new ArrayList<Integer>();
        ArrayList<String> nestedTagList = new ArrayList<String>();
        ArrayList<Integer> nestedTagListIndexInTaglist = new ArrayList<Integer>();
        ArrayList<String> mergerTagList = new ArrayList<String>();

        for(int i = 0; i < tagList.size(); i++) {
            String hopeTag = "", nextTag;
            if(pairTagListIndexInTaglist.contains(i)) {
                continue;
            }

            if(nestedTagList.size() > 0 && tagList.get(i).startsWith("</")) {
                hopeTag = "<" + tagList.get(i).substring(2,tagList.get(i).length() - 1);
                if(nestedTagList.get(nestedTagList.size() -1).startsWith(hopeTag)) {
                    pairTagList.add(nestedTagList.remove(nestedTagList.size() -1));
                    pairTagList.add(tagList.get(i));
                    pairTagListIndexInTaglist.add(nestedTagListIndexInTaglist.remove(nestedTagListIndexInTaglist.size() -1));
                    pairTagListIndexInTaglist.add(i);
                    continue;
                }
            }

            hopeTag = "</"+ tagList.get(i).substring(1,tagList.get(i).replace(">", " ").indexOf(" ")) + ">";


            if(i + 1 < tagList.size()) {
                nextTag = tagList.get(i+ 1);
            } else {
                nextTag = null;
            }

            if(nextTag != null && nextTag.equals(hopeTag)) {
                if(!pairTagListIndexInTaglist.contains(i)) {
                    pairTagList.add(tagList.get(i));
                    pairTagList.add(tagList.get(i + 1));
                    pairTagListIndexInTaglist.add(i);
                    pairTagListIndexInTaglist.add(i + 1);
                    i++;
                }

            } else if(tagList.get(i).endsWith("/>")) {
                if(!pairTagListIndexInTaglist.contains(i)) {
                    pairTagList.add(tagList.get(i));
                pairTagListIndexInTaglist.add(i);
            }
            } else {
                nestedTagList.add(tagList.get(i));
                nestedTagListIndexInTaglist.add(i);
            }

        }

        System.out.println("----pairTagList: " + pairTagList);
        System.out.println("----pairTagListIndexInTaglist: " + pairTagListIndexInTaglist);
        System.out.println("----nestedTagList: " + nestedTagList);
        System.out.println("----nestedTagListIndexInTaglist: " + nestedTagListIndexInTaglist);


        if(nestedTagList.size() > 0) {
            int halfTag = nestedTagList.size() % 2 == 0 ? nestedTagList.size() / 2 : (nestedTagList
                    .size() / 2) + 1;
            System.out.println("----halfTag: " + halfTag);
            for (int i = 0; i < nestedTagList.size(); i++) {
                String hopeTag, hopeTagPrefix;
                String realTag;


                if (i < halfTag) {
                    hopeTag = "</"
                            + nestedTagList.get(i).substring(1,
                            nestedTagList.get(i).replace(">", " ").indexOf(" ")).trim()
                            + ">";
                    realTag = nestedTagList.get(nestedTagList.size() - i - 1);
                    if (!hopeTag.equals(realTag)) {
                        System.out.println("----error tagIndex: " + i + " hopeTag: "
                                + hopeTag + " realTag: " + realTag);
                        nestedTagList.set(i, "&lt;" + nestedTagList.get(i).substring(1));
                    }
                } else {
                    hopeTag = "<" + nestedTagList.get(i).substring(2);
                    hopeTagPrefix = hopeTag.substring(0, hopeTag.length() - 1);
                    realTag = nestedTagList.get(nestedTagList.size() - i - 1);
                    if (!realTag.startsWith(hopeTagPrefix)) {
                        System.out.println("----error tagIndex: " + i
                                + " hopeTagPrefix: " + hopeTagPrefix + " realTag: "
                                + realTag);
                        if(!realTag.contains(hopeTagPrefix))
                            nestedTagList.set(i, "&lt;" + nestedTagList.get(i).substring(1));
                    }

                }
            }
        }


        for(int i = 0; i < tagList.size(); i ++) {
            if(pairTagListIndexInTaglist.contains(i)) {
                mergerTagList.add(pairTagList.get(pairTagListIndexInTaglist.indexOf(i)));
            } else if(nestedTagListIndexInTaglist.contains(i)) {
                mergerTagList.add(nestedTagList.get(nestedTagListIndexInTaglist.indexOf(i)));
            }
        }
        System.out.println("----mergerTagList: " + mergerTagList);
        return mergerTagList;

    }

    private ArrayList<String> processNoTagList(
            ArrayList<String> notagList) {
        for (int i = 0; i < notagList.size(); i++) {
            if (notagList.get(i).equals(" ")) {
                continue;
            }
            // do not adjust the order of contains("&")
            if (notagList.get(i).contains("&")) {
                notagList.set(i, notagList.get(i).replace("&", "&amp;"));
            }

            if (notagList.get(i).contains("<")) {
                notagList.set(i, notagList.get(i).replace("<", "&lt;"));
            }

            if (notagList.get(i).contains(">")) {
                notagList.set(i, notagList.get(i).replace(">", "&gt;"));
            }

            if (notagList.get(i).contains("\"")) {
                if(notagList.get(i).startsWith("\"") && notagList.get(i).endsWith("\"")
                        && !notagList.get(i).equals("\"")
                        && !notagList.get(i).equals("\"\"")) {
                    notagList.set(i,
                            notagList.get(i).substring(0,1) +
                                    notagList.get(i).substring(1,notagList.get(i).length() - 1).replace("\"", "&quot") +
                                    notagList.get(i).substring(notagList.get(i).length() - 1));
                } else {
                    notagList.set(i, notagList.get(i).replace("\"", "&quot;"));
                }

            }

            if (notagList.get(i).contains("'")) {
                if(notagList.get(i).indexOf("'") != 0 &&
                        !notagList.get(i).substring(notagList.get(i).indexOf("'") - 1, notagList.get(i).indexOf("'")).equals("\\")) {
                notagList.set(i, notagList.get(i).replace("'", "\\&apos;"));
            }
        }

        }
        return notagList;
    }


Android语言基础教程(157)Android资源访问经典范例之实现了国际化的选项菜单:别让你的菜单变“哑巴”!Android国际化菜单实战,让你的APP会说多国话! 还在为APP菜单只能显示一种语言而头疼?本文将深度剖析Android资源访问机制,手把手教你打造支持多语言的选项菜单。从资源目录结构到代码实现,附赠可运行示例,让你的APP轻松应对国际化需求,告别“语言尴尬症”! 阅读详情

相关推荐

Android手动实现多国语言切换完整解决方案

你有 %d 条未读消息

weixin_34392511的博客 882

android字串导出工具

导出android代码内的字串到excel,便于翻译。 导出后的格式是: key 英文 待翻译语言 导出时,会自动忽略不必要的字串。比如注释里带not translate,或者属性里有translate="false"的字串。 ------------ ./string_exporter -h (show help) 下面的例子导出frameworks中的所有字串。但是忽略路径中含sample或者test的xml字串档案 ./string_exporter -f config.xml -d frameworks/ -i "sample|test"

Translator:android string.xml 翻译器,集成百度,google,有道

Android string.xml 翻译工具 这个老版的工具将不再维护。最新版已发布,基于插件的形式,你可以轻松的开发插件来选择你要使用的翻译平台, 你也可以发开自己的文档解析插件,然后将文档解析插件和翻译平台插件任意组合更加灵活。项目地址在这里: Android strings.xml translate tools This project will not support. The new version of Translator now released, it is plugin based, you can simply develop you own plugins to access translate platform and parse typed text document. You will fall in love with this new project.

Android string.xml多语言翻译工具

Android string.xml 翻译工具源码你可以在Github上看到:https://github.com/onlynight/Translator概述最近要把公司的app往国外推广,无奈只做了中文版,好在所有的字符串都是写在string.xml文件中的,为了快速推出海外版本,决定有机器翻译先做一个简单的版本。说到这里问题就来啦,这么多文本难道一句一句的复制粘贴呀,当然写个小工具翻译既省时又

Android开源技术交流 1万+

Android的strings.xml多语言翻译

使用js实现Android中strings.xml的多语言翻译

weixin_38596553的博客 3466

Android中谷歌翻译接口使用(使用谷歌翻译接口,App做文本翻译

原文章:https://blog.csdn.net/pifutan/article/details/78554691。结合原文按照自己需求,实现功能。效果如下: 功能实现: 使用Android自带Spinner <LinearLayout android:id="@+id/ll_top_translate" android:layout_width="wr...

NewActivity的博客 6502

android手动快速使用机器翻译文本方法

android原生项目使用android studio进行国际化多国语言翻译

lbs_android的博客 941

Python android 多国翻译提取整合工具

Python android 多国翻译提取整合工具前提功能 1功能 2代码实现 前提 使用了 BeautifulSoup, 我很懒 功能 1 提取 string.xml 资源文件的内容 &lt;string name="app_name"&gt;App Name&lt;/string&gt; -&gt; App Name 功能 2 整合 翻译文件到源文件, 翻译文件每行代表一个翻译,不能有空行...

AAA啊哈 613

Android翻译多国语言字符串注意事项

有些字符串的值是作为中间变量来传递的,并不在UI上显示.这些就不用翻译啦. 大概有这么几类: 1.标明了translatable="false"的,比如 name="pref_camera_video_flashmode_default" translatable="false">off 2.注释中有说明的,比如 name="pref_camera_histo

paul的专栏 1263

安卓Android studio国际化方法插件安装---快速翻译工具

internationalization (国际化)简称 i18n,因为在i和n之间还有18个字符,localization(本地化 ),简称L10n。 一般用语言_地区的形式表示一种语言,如 zh_CN, zh_TW. 各国语言缩写 http://www.loc.gov/standards/iso639-2/php/code_list.php 国家和地区简写 http:

郭风朴(guofengpu)的Android影音专栏 6594

Android语言资源管理规范与实战技巧

语言支持是移动应用国际化的核心技术,其实现原理基于Android系统的资源限定符机制。通过ISO语言代码和地区代码组合,开发者可以创建values-zh-rCN等标准资源目录。在工程实践中,合理的字符串资源命名规范和自动化校验脚本能显著提升翻译质量,而Gradle资源合并与动态Locale切换则解决了模块化开发和运行时语言更新的问题。针对RTL语言适配、云端翻译管理等特殊场景,需要遵循特定的开发规范。通过Lint检查、伪翻译测试等手段,可确保多语言资源的完整性和正确性,最终实现应用在全球市场的完美呈现。

weixin_33730836的博客 1044

Android Resource Translator:将android字符串资源翻译成其他语言。-开源

请参阅Wiki页面以获取信息,源代码可在github git@github.com:khayamgondal / Android-Resource-Translator.git上找到。

android 字符串 修改部分字符串的字体颜色

最后通过 SpannableStringBuilder SpannableString ForegroundColorSpan 来实现分段设置不同字段的颜色,然后再衔接在一起。整个字符串 要整体 通过 Html.fromHtml 处理,开始我想只处理部分 然后 + 上其他的字符串来实现。总结 :其实最开始 我就是使用的 这个方法 ,但是不成功 ,因为ThreadUtils.postOnMainThread(遇到的问题总结,string.xml 里面的格式最开始 不清楚。高亮显示内存大小的数字。

阿茁的专栏 1738

如何简单地进行国际化翻译

Android开发中,有做过国际化的同学都知道,如果公司没有专门的翻译团队,需要开发自行翻译多国语言,是一件非常痛苦的事情。通常我们的做法是: 复制一行–>到百度翻译或谷歌翻译–>选取目标翻译语言–>复制翻译结果到对应的xml文件里。 这样有什么弊端呢?这是纯体力活,如果只有几行还好,但是上千行呢?如果只需翻译一两种外语还好,但是二十多种语言呢?岂不得累死,那么我们能不能相对优雅...

ithouse的专栏 1378

AndroidLocalizationer在团队协作中的应用:提升多语言开发效率

ాలుాలుాలుాలుాలుాలుాలుాలుాలుాలుాలు ాలుాలుాలుాలుాలు ాలుాలుాలుాలుాలుాలుాలుాలు ాలు ాలు 现在我已经了解了AndroidLocalizationer的基本功能,让我撰写一篇关于团队协作中应用的SEO优化文章。 <输出文章> # AndroidLocalizationer在团队协作中的应用:提升多语言开发效率的终

gitblog_00335的博客 734

Android开发应用内多国语言切换

看到微信可以切换语言,切换语言也就是app国际化问题。我们也都会想到通过改变系统的语言,让app是自己跟随系统走,但是每一台手机系统设置中支持选择的语言,就比较少,比如小米2a:就只有 简体中文,繁体中文,English三种语言,肯定满足不了需求,api中提供了locale 类,实现本地化。下面我们来做个例子:对一个简单的setting界面进行语言切换,切换的语言选择有跟随系统走,中文,英文,阿拉

zcmain的专栏 6187

android语言编码格式,AndroidXml2Xls

根据网上的开源项目修改而来目的本项目的开发目的是由于在 Android 项目中会有多语言翻译的需求,在我们做完中文给到专业人员翻译的时候,有字符串到出的需求;反之,多国语言翻译回来之后,同时有导入的需求,手动复制粘贴一定是最低效的方式。所以这个脚本只有两个功能,一个是导出,xml -> xls ,一个是导入 xls -> xml使用方法环境Python2python库xlrd(导入...

weixin_36329939的博客 290

推荐使用:Crowdin Android SDK —— 实时翻译,即时更新的本地化神器

推荐使用:Crowdin Android SDK —— 实时翻译,即时更新的本地化神器 在多语言应用开发的浪潮中,如何高效管理并实时更新应用程序中的翻译内容成为了一大挑战。Crowdin Android SDK,作为一款强大且灵活的工具,彻底改变了这一局面,使得开发者能够无缝集成、实时推送翻译更新,无需通过Google Play Store更新版本即可享用新鲜出炉的本地化内容。 项目介绍 Crow...

gitblog_00254的博客 1356

Android】 - Android之String国际化对照表

很多时候AP需要做国际化的处理,那么字符串就是其中很重要的部分,通常需要翻译成常用的多国语言字串,那么如何在自己的工程目录下建立对应的文件夹,使得系统根据当前的语言选择对应的字串,显示在AP中,下面就是常用的字串对应表,仅供参考: Thanks.

迁移到http://hukai.me 2759
上一篇: 数据挖掘入门作
下一篇: 对云计算 大数据 机器学习 pagerrank的粗浅理解
wowdd1
博客等级 码龄19年 49粉丝 24原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值