iOS/iPhone:嵌套的Localizable.strings文件?

6

我正在开发一个应用程序,它将有多个变种。

这些变种将由多个Localizable.strings文件中的一些字符串进行控制。

然而,90%的字符串都将保持不变。

我希望每个唯一的Localizable.strings文件都能导入“主”文件,这样当我想要更改通用字符串时,就不必逐个更改每个应用程序变体文件。

这种做法是否可行?

5个回答

7

两种选择:

  1. 使用自定义包装函数围绕 NSLocalizedString 来为您进行分层查找,然后在默认情况下回退到 NSLocalizedString 机制。

    我之前写过一篇关于如何做到这一点的答案:Can .strings resource files be added at runtime?

  2. 每种语言使用多个 .strings 文件。默认情况下会在 "Localizable.strings" 中查找东西,但是 NSLocalizedStringFromTable() 函数允许您指定自定义的 "table" 名称。所以如果您传递 "Configuration" 作为表名,它将在 "Configuration.strings" 文件中查找东西。

    我曾经在一个应用程序上工作过,它就是这么做的。我们有两个不同的 .strings 文件。一个控制品牌设置(使用什么名称、使用什么图像、使用什么服务器等),另一个包含所有实际翻译的字符串。应用程序包中只有一个品牌信息拷贝,并且我们使用一些自定义脚本在编译时选择要使用的正确变体。它运行得非常好。


谢谢。我很感激。要做正确的事情,我可能需要进行一些研究,但选项2非常有道理。Perl脚本对我很有用,我已经使用了几天(和许多变体),所以我将在这个项目中坚持使用它。 - Chris Marshall

2

很遗憾,苹果不支持在其 Localizable.strings 文件中实现该功能。

你可以通过编写自定义的 Ruby 或 Python 脚本或者使用 Bash 脚本(使用 sed 命令),来模拟此功能;该脚本可以将根目录的 .strings 文件的内容复制到每个变体的 .strings 文件中。甚至可以把它作为自定义构建步骤添加到 Xcode 中。


谢谢。这正是我所想的。 - Chris Marshall

1

好的。这是我解决它的方法。

我从Git存储库中删除了各种Localizable.strings文件,但将它们留在它们的位置(每个应用程序变体目录中有一个)。

我只取了每个变体之间不同的几行,并将它们分成一个单独的文本文件,称为“MyLocalizable.strings”。我将它们添加到Git中,并将它们添加到项目中,但不与任何目标相关联。我将Localizable.strings文件与每个目标相关联。

因此,我们拥有的是每个目标都有一个与目标相关联并将被复制到bundle中的Localizable.strings文件。每个目标目录都有一个名为“MyLocalizable.strings”的文件,其中仅包含从目标到目标变化的少数字符串。

然后,我将绝大多数字符串 - 那些不会改变的字符串 - 放入另一个名为“MyLocalizable.strings”的文件中,并将其放置在中央(公共)目录中。同样,我将其添加到Git和项目中,但不与任何目标相关联。

接下来,我编写了一个非常小且可怜的Perl脚本,用于构建Localizable.strings文件。该脚本从公共文件中获取内容并将其附加到特定目标的文件中,从而创建一个新的Localizable.strings文件,并覆盖现有的文件。这意味着每次运行脚本时都会生成新的Localizable.strings文件。该脚本位于公共区域,并添加到项目中,但不与任何目标相关联。该脚本只需要一个参数,即目标名称(以及其目录)。其语法如下:

#!/usr/bin/perl

use strict;         # I'm anal. What can I say?
use Cwd;            # We'll be operating on the working directory.
use File::Path;

my $input1File = cwd()."/BMLT/Supporting\ Files/en.lproj/MyLocalizable.strings";
my $input2File = cwd()."/".$ARGV[0]."/en.lproj/MyLocalizable.strings";
my $outputFile = cwd()."/".$ARGV[0]."/en.lproj/Localizable.strings";

open ( MAIN_FILE, $input1File ) || die ( "Could not open main file!" );

my @file_data = <MAIN_FILE>;

close ( MAIN_FILE );

open ( PRODUCT_FILE, $input2File ) || die ( "Could not open product file!" );

push ( @file_data, <PRODUCT_FILE> );

close ( PRODUCT_FILE );

open ( FINAL_FILE, ">$outputFile" ) || die ( "Could not open destination file!" );

foreach ( @file_data ) print FINAL_FILE $_;

close ( FINAL_FILE );

我随后在“复制包资源”步骤之前添加了一个“运行脚本”构建步骤。该脚本使用以下语法调用Perl脚本:
${PROJECT_DIR}/BMLT/Supporting\ Files/buildLocalizationFile.pl ${PRODUCT_NAME}

当构建完成后,文件将被合并,并将合并的文件放入捆绑包中。


我认为这是解决这个问题的完美方案。谢谢,我今天会尝试一下。 - Charith Nidarsha

1

我不确定你想要什么,但如果你只是想翻译几个字符串,那么你可以这样做。

你可以只翻译这些字符串的一部分,如果没有翻译,iOS 将选择应用程序语言中的字符串并显示它。因此,应用程序语言中的 Localizable.strings 可以被视为主文件。


谢谢。然而,那不是我真正需要的。每个显示的字符串都来自Localized.strings文件。但是,只有很少的字符串在应用程序变体之间发生变化。绝大多数字符串都是相同的。这意味着我必须为每个变体制作整个文件的副本。然后,当我添加或更改字符串时,我需要进入每个变体,并更改该字符串。很容易犯错误。我更喜欢将所有共享字符串放在一个文件中,然后将其包含到变体的特定文件中。但是,.strings文件似乎是一种自定义格式。 - Chris Marshall

1
为所有目标创建一个通用的Localizable.strings文件,包含共用字符。同时为每个目标创建TargetSpecificLocalizable.strings文件,并将目标特定字符保存其中。对于共用字符,请使用。
NSLocalizedString("sample string", comment: "")

并且针对特定的字符串使用,使用


NSLocalizedString("sample string", tableName: "TargetSpecificLocalizable", bundle: Bundle.main, value: "", comment: "")

这是一个非常好的实践,但在 OP 的情况下,它不起作用,因为执行代码不会知道使用备用字符串文件。 - Chris Marshall

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接