如何获得本地化的“取消”、“完成”等功能?

51

UIBarButtonItem具有Cancel、Done和其他一些标识符。它们以文本形式显示给用户。如果用户更改语言,例如取消按钮将自动翻译。作为开发人员,您不需要为这些按钮提供本地化字符串。这意味着Cancel、Done和其他字符串已经本地化,并随操作系统一起提供。

是否有一种方法可以通过编程方式获取这些字符串?

我不想向本地化文件添加额外的字符串。如果可以访问,则非常好。


你不能通过标题属性访问字符串吗? - tiguero
2
如果这个UIBarButtonItem被放在UI中,我可以获取它的标题。但是我想要获取这个翻译,并且不使用变通方法。 - Ramis
你的UIBarButtonItem.title属性可以让你获取显示的字符串 - 这是你想要的吗? - tiguero
2
我知道我可以获取此按钮的标题。正如我之前所写的,取消、完成和其他字符串已经随着所有本地化一起随操作系统提供。我想要的是访问操作系统中的这些字符串。 - Ramis
@tiguero 这个问题是合理的:您可能想要在不创建按钮的情况下获取本地化字符串。 - Nikolai Ruhe
显示剩余2条评论
8个回答

33

这是我创建的一个小宏,用于获取系统UIKit字符串:

#define UIKitLocalizedString(key) [[NSBundle bundleWithIdentifier:@"com.apple.UIKit"] localizedStringForKey:key value:@"" table:nil]

像这样使用:

UIKitLocalizedString(@"Search");
UIKitLocalizedString(@"Done");
UIKitLocalizedString(@"Cancel");
...

2
有没有办法获取所有的键? - kelin
1
我现在将我的测试从Swift转换为XCUI,但它不再起作用了 :( - Bruno Muniz
4
这个已经不起作用了,对吧?UIKit包中不再有Localized.string文件。实际上,在搜索运行时模拟器文件后,我甚至无法确定这些字符串的位置在哪里。 - androidguy
不再工作是因为bundleWithIdentifier调用。将其替换为bundleForClass,它就能再次工作了。请参见我的答案示例。 - scosman

13

一种(尽管有争议的)轻松完成此事的方法是直接使用苹果的框架束本地化:

要查看它们提供了什么,请通过Finder打开以下目录:

/Applications/Xcode/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator6.1.sdk/System/Library/Frameworks

在您的情况下,您随后将打开./UIKit.framework/English.lproj/Localizable.strings (在TextMate中)。在这里,您可以看到苹果用于"Print"、"OK"、"On"、"Off"等内容的各种翻译。真正的奇迹在于,您可以免费复制约35种不同的语言翻译到自己的Localizable.strings文件中。

如果您非常大胆且不介意将应用程序的未来稳定性置于问题中,则可以跳过整个“将其复制到自己的Localizable.strings”过程并直接从源代码执行:

NSBundle *uiKitBundle = [NSBundle bundleWithIdentifier:@"com.apple.UIKit"];
NSString *onText = uiKitBundle ? [uiKitBundle localizedStringForKey:@"Yes" value:nil table:nil] : @"YES";
NSString *offText = uiKitBundle ? [uiKitBundle localizedStringForKey:@"No" value:nil table:nil] : @"NO";

注意:我绝不建议您在打算提交到App Store的应用程序中以编程方式访问这些本地化资源。我只是演示了一个特定的实现,以解决您最初的问题。



有人知道在Xcode 11中这些本地化的.strings文件现在存放在哪里吗?似乎SDK内的所有框架路径都只有头文件,没有字符串文件。 - androidguy

9

这个问题(由Stephan Heilner提出)和答案(由bdunagan提供)的鼓舞下,寻找iPhone/iOS:如何获得应用程序中所有本地化字符串的语言列表?

Objective-C

NSString * LocalizedString(NSString *key) {
    return [[NSBundle mainBundle] localizedStringForKey:key];
}

@interface NSBundle(Localization)
- (NSString *)localizedStringForKey:(NSString *)key;
- (NSDictionary<NSString *, NSString *> *)localizationTable;
@end

@implementation NSBundle(Localization)
- (NSDictionary<NSString *, NSString *> *)localizationTable {
    NSString *path = [self pathForResource:@"Localizable" ofType:@"strings"];
    NSData *data = [NSData dataWithContentsOfFile:path];
    NSError *error = nil;
    id obj = [NSPropertyListSerialization propertyListWithData:data options:NSPropertyListImmutable format:NULL error:&error];
    if (error && obj == nil) {
        @throw error;
        return nil;
    }
    if ([obj isKindOfClass:NSDictionary.class]) {
        return obj;
    }    
    @throw NSInternalInconsistencyException;
    return nil;
}

- (NSString *)localizedStringForKey:(NSString *)key {
    return [self localizedStringForKey:key value:nil table:nil];
}
@end

Swift 5

public extension String {
    func localized(_ bundle: Bundle = .main) -> String {
        bundle.localize(self)
    }        
    var localized: String {
        return localized()
    }
}

extension Bundle {
    static var UIKit: Bundle {
        Self(for: UIApplication.self)
    }
    func localize(_ key: String, table: String? = nil) -> String {
        self.localizedString(forKey: key, value: nil, table: nil)
    }
    var localizableStrings: [String: String]? {
        guard let fileURL = url(forResource: "Localizable", withExtension: "strings") else {
            return nil
        }
        do {
            let data = try Data(contentsOf: fileURL)
            let plist = try PropertyListSerialization.propertyList(from: data, format: .none)
            return plist as? [String: String]
        } catch {
            print(error)
        }
        return nil
    }
}

使用方法:

"Photo Library".localized(.UIKit)

获取所有UIKit本地化字符串的键:
Bundle.UIKit.localizableStrings?.keys//.map { $0 }

4

虽然可能不是你正在寻找的完全内容,但在Mac应用商店中有一个名为“System Strings”的商业应用程序声称提供了超过53000个标准本地化字符串的集合。该应用程序于2012年11月2日发布。我与此应用程序或作者无任何关联。URL是https://itunes.apple.com/us/app/systemstrings/id570467776


是的,这不是我想要的,但它看起来很好。非常接近要点。 - Ramis

1
听起来你在问的是苹果是否提供一种访问预翻译字符串字典的方法。我认为,像这样的任何由苹果提供的内容都会位于他们的文档中:国际化编程主题
回答你的问题,我认为他们没有提供已知翻译的字典/清单。你必须将它们定义在你的 Localizable.strings 资源文件中,或者按照其他评论中所述从 UIBarButtonItem 中提取标题(我个人会选择资源文件)。

1

iOS 16 中的工作版本。之前的版本似乎不再起作用了。

+(NSString*) uiKitLocalizedStringForKey:(NSString*)key {
    NSBundle* uikitBundle = [NSBundle bundleForClass:[UIButton class]];
    if (!uikitBundle) {
        // Never seen this happen, but might as well guard for it
        return key;
    }
    return [uikitBundle localizedStringForKey:key value:key table:nil];
}

0

为什么不在你的Storyboard中使用基本本地化呢?它会自动为你进行本地化。


1
我需要访问这些内容以进行一些KIF集成测试。 - Stephan Heilner

-6
你可以使用。
NSLocalizedString(@"Cancel", @"Cancel")

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