避免翻译 XCode 项目中的标准菜单项

发布于 2024-10-02 23:18:41 字数 198 浏览 5 评论 0原文

我有一个 XCode 项目,其中包含使用 Interface Builder 构建的 XIB 接口文件。我正在通过使用 ibtool 提取字符串、翻译字符串并再次使用 ibtool 构建本地化 XIB 文件来构建本地化 XIB 文件。

然而,这样做意味着我必须翻译应用程序菜单中的所有项目,包括那些完全标准的项目(文件、保存、打开、最小化等)。有办法避免这种情况吗?

I have an XCode project, with the XIB interface files built using Interface Builder. I'm building localized XIB files by using ibtool to extract strings, translating them, and using ibtool again to build localized XIB files.

However, doing this means I have to translate all items in the application menus, including those that are completely standard (File, Save, Open, Minimize, etc.). Is there a way to avoid that?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

暖阳 2024-10-09 23:18:41

我已经开发了解决这个问题的方法。

https://www.corecode.io/index_opensource.html

寻找“Translator”,它将使用标准菜单项字符串的标准 Apple 翻译将您的 MainMenu.strings 文件翻译成十几种语言。

如果您发现 Aapple 在其基础应用程序中缺少某些字符串或语言,请发送补丁。

i've developed a solution to this problem.

https://www.corecode.io/index_opensource.html

look for "Translator", it will translate your MainMenu.strings file into a dozen languages with the standard Apple translations for the standard menu item strings.

if you find some strings or languages missing that Aapple has included in their base apps, please send a patch over.

还给你自由 2024-10-09 23:18:41

所以,显然没有办法解决这个问题。

So, apparently no way around this.

怎会甘心 2024-10-09 23:18:41

我一直在寻找类似的解决方案一段时间,我发现了这个资源

http://www.bdunagan.com/2009/03/15/ibtool-localization-made-easy/

它在文章末尾引用了:

ibtool 将在 MainMenu.xib 中查找每个用户可见的字符串,并将该字符串与关联的 ObjectID 插入到 MainMenu.strings 中,MainMenu.strings 本质上是一个由 ObjectID 键入的字符串字典。更好的是,该工具按 ObjectID 对它们进行排序,因此版本化的 .strings 文件可以很好地进行区分。我可以轻松查看添加、删除或更改了哪些字符串。让我重复一遍,因为它非常方便:.strings 文件差异很好!当然,这些 .strings 文件是 unicode,因此它们不可 grep'able。下面是字符串输出的示例:

继续看一下,我真的希望它对您有帮助,就像它对我有帮助一样!

I have been looking for a similar solution for a while and I found this resource

http://www.bdunagan.com/2009/03/15/ibtool-localization-made-easy/

It quotes toward the end of the article:

ibtool will look through MainMenu.xib for every user-visible string and insert that string with an associated ObjectID into MainMenu.strings, essentially a dictionary of strings keyed by ObjectID. Even better, the tool sorts them by ObjectID, so versioned .strings files are nicely diff’able. I can easily see what strings are added, removed, or just changed. Let me repeat this because it’s so incredibly handy: .strings files diff well! Of course, these .strings files are unicode, so they are not grep’able. Below is an example of the output for a string:

Go ahead and take a look I really hope it helps you as much as it helped me!

长途伴 2024-10-09 23:18:41

翻译者 https://github.com/core-code /MiscApps/blob/master/Translator/Translator/MainMenuTranslations.plist
很酷,但如果你不想在构建中处理 30 个 MainMenu.string 文件(我个人不想) - 你可以将 MainMenuTranslations.plist 添加到你的资源中(未压缩的 230KB 很小)并像这样即时执行这个:

- (void) processMenu: (NSString*) app {
    NSDictionary* d = [self loadMenuTranslations: app];
    NSMenu* mm = NSApplication.sharedApplication.mainMenu;
    for (int i = 0; i < mm.numberOfItems; i++) {
        NSMenuItem* mi = [mm itemAtIndex: i];
        mi.title = [self translateMenu: mi.title withDictionary: d];
        NSMenu* sm = [[mm itemAtIndex: i] submenu];
        sm.title = [self translateMenu: sm.title withDictionary: d];
        for (int j = 0; j < sm.numberOfItems; j++) {
            NSMenuItem* mi = [sm itemAtIndex: j];
            mi.title = [self translateMenu: mi.title withDictionary: d];
        }
    }
}

- (NSString*) translateMenu: (NSString*) key withDictionary: (NSDictionary*) dictionary {
    for (NSString* lang in dictionary) {
        NSDictionary* translation = dictionary[lang];
        NSString* t = translation[key];
        if (t != null) {
            return t;
        }
    }
    return key;
}

- (NSDictionary*) loadMenuTranslations: (NSString*) app {
    NSArray* langs = [NSUserDefaults.standardUserDefaults objectForKey: @"AppleLanguages"];
    NSURL* url = [NSBundle.mainBundle URLForResource:@"MainMenuTranslations.plist" withExtension: null];
    NSMutableDictionary* r = NSMutableDictionary.new;
    NSDictionary* translations = [NSDictionary dictionaryWithContentsOfURL: url];
    for (NSString* lang in langs) {
        NSString* locale = [NSString stringWithFormat:@"%@.lproj", lang];
        NSDictionary* translation = translations[locale];
        NSMutableDictionary* d = [NSMutableDictionary.alloc initWithCapacity: translations.count * 3 / 2];
        for (NSString* k in translation) {
            NSString* v = translation[k];
            NSString* key = k;
            if ([k indexOf: @"APPLICATIONNAME"] >= 0) {
                key = [k stringByReplacingOccurrencesOfString: @"APPLICATIONNAME" withString: app];
            }
            if ([v indexOf: @"APPLICATIONNAME"] >= 0) {
                v = [v stringByReplacingOccurrencesOfString: @"APPLICATIONNAME" withString: app];
            }
            d[key] = v;
        }
        if (d.count > 0) {
            r[lang] = d;
        }
    }
    return r;
}

只需从“我希望某处有一个 UniversalTranslation.plist”中调用它

- (void) applicationDidFinishLaunching: (NSNotification*) n {
    // ...
    [self processMenu: @"<your app name>"];
}

(可以通过创造性地使用 translate.google.com 自动收集)

Translator by https://github.com/core-code/MiscApps/blob/master/Translator/Translator/MainMenuTranslations.plist
is cool but if you do not want to deal with 30 MainMenu.string files in your build (I personally don't) - you can just add MainMenuTranslations.plist to your resources (230KB uncompressed is tiny) and do it on the fly like this:

- (void) processMenu: (NSString*) app {
    NSDictionary* d = [self loadMenuTranslations: app];
    NSMenu* mm = NSApplication.sharedApplication.mainMenu;
    for (int i = 0; i < mm.numberOfItems; i++) {
        NSMenuItem* mi = [mm itemAtIndex: i];
        mi.title = [self translateMenu: mi.title withDictionary: d];
        NSMenu* sm = [[mm itemAtIndex: i] submenu];
        sm.title = [self translateMenu: sm.title withDictionary: d];
        for (int j = 0; j < sm.numberOfItems; j++) {
            NSMenuItem* mi = [sm itemAtIndex: j];
            mi.title = [self translateMenu: mi.title withDictionary: d];
        }
    }
}

- (NSString*) translateMenu: (NSString*) key withDictionary: (NSDictionary*) dictionary {
    for (NSString* lang in dictionary) {
        NSDictionary* translation = dictionary[lang];
        NSString* t = translation[key];
        if (t != null) {
            return t;
        }
    }
    return key;
}

- (NSDictionary*) loadMenuTranslations: (NSString*) app {
    NSArray* langs = [NSUserDefaults.standardUserDefaults objectForKey: @"AppleLanguages"];
    NSURL* url = [NSBundle.mainBundle URLForResource:@"MainMenuTranslations.plist" withExtension: null];
    NSMutableDictionary* r = NSMutableDictionary.new;
    NSDictionary* translations = [NSDictionary dictionaryWithContentsOfURL: url];
    for (NSString* lang in langs) {
        NSString* locale = [NSString stringWithFormat:@"%@.lproj", lang];
        NSDictionary* translation = translations[locale];
        NSMutableDictionary* d = [NSMutableDictionary.alloc initWithCapacity: translations.count * 3 / 2];
        for (NSString* k in translation) {
            NSString* v = translation[k];
            NSString* key = k;
            if ([k indexOf: @"APPLICATIONNAME"] >= 0) {
                key = [k stringByReplacingOccurrencesOfString: @"APPLICATIONNAME" withString: app];
            }
            if ([v indexOf: @"APPLICATIONNAME"] >= 0) {
                v = [v stringByReplacingOccurrencesOfString: @"APPLICATIONNAME" withString: app];
            }
            d[key] = v;
        }
        if (d.count > 0) {
            r[lang] = d;
        }
    }
    return r;
}

just call it from

- (void) applicationDidFinishLaunching: (NSNotification*) n {
    // ...
    [self processMenu: @"<your app name>"];
}

I wish there is a UniversalTranslation.plist somewhere (which could be probably collected automatically via creative use of translate.google.com)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文