典型的java i18n进程 - 将资源文件发送给翻译公司进行翻译

时间:2010-09-15 21:18:46

标签: java internationalization resourcebundle

有大量关于使用Java ResourceBundles以多种语言提供UI的教程。但是,关于与翻译公司的典型互动,我有一个进程问题,我似乎无法找到答案。

假设我不懂法语,需要聘请翻译公司为我的应用程序翻译,我会发送给他们吗

  1. 默认资源属性文件“whatever_en_US.properties”包括密钥和英文值,并返回“whatever_fr_FR.properties”?
  2. “whatever_fr_FR.properties”,空值和“whatever_en_US.properties”供参考?
  3. 其他一些组合?

2 个答案:

答案 0 :(得分:4)

由于您的问题是关于流程而不是技术问题,我将尽力给您详尽的解释。假设您的应用程序没有先前的翻译,理想的过程应如下所示:

  1. 发送英文文件进行翻译。根据您与翻译承包商的协议,您可以使用:

    • 您的默认属性文件(您将负责正确地重命名)
    • Excell电子表格,其中包含键,英语短语和用于翻译的空列
    • Gettext * .po文件,如果您要使用gettext
    • 翻译记忆库文件(即Trados * .tmx文件)
  2. 当您收到文件时,您将这些翻译放入产品,创建本地化版本并测试它。肯定会有一些UI问题。其中一些你可以自己修复,一些需要额外的翻译(如硬编码字符串),其他则需要缩短翻译。同样,您将聘请翻译承包商并为他们提供需要(重新)翻译的字符串。你可以在这里使用电子表格(假设没有那么多字符串需要翻译)。

  3. 如果您想同时发货(所有语言一次发货),您需要尽早聘请译员。由于UI字符串将发生变化(假设没有硬UI冻结期或翻译冻结期),您必须更新您的翻译。在这种情况下,您需要提供已翻译的文件以及需要翻译的字符串(英文)。如果更改非常小,您可以只发送英文字符串并手动合并翻译,否则最好使用某种翻译记忆库交换格式(gettext * .po或trados * .tmx在这里很棒)。

  4. 翻译文件通常是不够的。由于通常没有给出上下文,并且不同的单词可能意味着目标语言中的不同内容,因此发生翻译错误。除非你懂语言,否则没有办法知道他们在。这就是为什么您需要获取UI屏幕截图并将其发送出去进行审核(可以由您的翻译承包商或其他人根据质量要求进行审核)。

  5. 审核完成后,您需要应用翻译更改并测试用户界面问题...

  6. 即便如此,如果我们谈论的是UI字符串翻译过程。但请注意,要正确本地化应用程序(文档,帮助文件,图标,颜色,声音......)还有很多其他内容。

答案 1 :(得分:2)

要回答你的问题,我会选择(2)。

在实践中,我发现对我来说使用其他东西比使用Java资源包要容易得多。

我个人使用不同的处理方法。我使用gettext方式(有一个名为GetTextResource.java的文件,您必须在应用程序中使用该文件才能从gettext扩展中受益 - 请参阅here)。

如果您熟悉gettext,您肯定会发现这种方法更容易实用。您只需向翻译人员提供po文件(可以使用poedit进行编辑)。从po文件中创建将在应用程序中使用的java类(这是使用msgfmt完成的 - 为po文件的java编译指定参数)。使用xgettext命令(从命令行)可以非常轻松地更新Po文件。

当然一切都在gettext manual内。

优点:

  • gettext为您提供了一种选择复数形式的方法[不再有以下消息:“N个文件已删除”(其中N是数字) - 请参阅ngettext

    < / LI>
  • 一个用新标记更新java文件后翻译字符串的脚本方法

  • 无需使用某些宏访问每个字符串(如Translate(DELETE_BUTTON_MACRO))。你只需编写这样的代码:

    package translateutil;        
    import gnu.gettext.GettextResource;
    
    import java.util.ResourceBundle;
    
    import java.util.Locale;
    
    public class TranslateUtil
    {
    private static ResourceBundle myResources =null;
    
    public static boolean init(Locale loc, String resourceName)
    {
        boolean bRet = true;
        Locale.setDefault(loc);
    
        try
        {
            myResources = ResourceBundle.getBundle(resourceName);
    
            System.out.printf(  _("Current language: %s\n"),
                                Locale.getDefault().getDisplayName() );
    
            System.out.printf(  _("%s resource found\n"),
                                myResources.getClass().getName() );
        }
        catch(Exception e)
        {
            // let the application go on in English in case the ResourceBundle
            // was not found. Notify about the error
            bRet = false;
            System.out.println( e.toString() );
            myResources = null;
        }
    
        return bRet;
    }
    
    
    public static String _(String str)
    {
        if (myResources == null)
        {
            return str;
        }
        {
            return GettextResource.gettext(myResources, str);
        }
    }
    
    public static String _Plural(String singular, String plural, long param)
    {
        if (myResources == null)
        {
            if (param == 1)
            {
                return singular;
            }
            else
            {
                return plural;
            }
        }
        else
        {
            return GettextResource.ngettext(myResources, singular, plural, param);
        }
    }
    }
    

这是一个示例

    // example
    // similar for plural

    import static translateutil.TranslateUtil._;

    System.out.println(_("The english text"));

无论你选择什么:祝你好运!