Localization

PSPDFKit comes with many languages already built-in:

  • Arabic (ar) (Including R2L interface support)
  • Chinese Simplified / Chinese Traditional (zh-Hans/zh-Hant)
  • Croatian (hr)
  • Czech (cs)
  • Danish (da)
  • Dutch (nl)
  • English (en)
  • Finnish (fi)
  • French (fr)
  • German (de)
  • Greek (el)
  • Indonesian (id)
  • Italian (it)
  • Japanese (ja)
  • Korean (ko)
  • Malay (ms)
  • Norwegian Bokmål (nb-NO)
  • Polish (pl)
  • Portuguese Brazil / Portugal (pt/pt-PT)
  • Russian (ru)
  • Serbian (sr)
  • Slovak (sk)
  • Slovenian (sl)
  • Spanish (es)
  • Swedish (sv)
  • Thai (th)
  • Turkish (tr)
  • Ukrainian (uk)

They are used automatically depending on the preferred language. To enable these, your application must also be localized in that language - otherwise PSPDFKit will fall back to English (else you would get a partly translated app which isn't a good user experience).

To translate your app, follow Apple's localization guidelines and provide your .strings file in all languages you want to support.

You can also use PSPDFKit's PSPDFSetLocalizationDictionary or PSPDFSetLocalizationBlock to customize the localization.

Note: iTunes Connect does not support all of these languages, but iOS devices can still be set to these languages, there's just no localized store front. See this list for a detailed listing.

Add further localization to PSPDFKit

You can either add further localization via adding the corresponding folders or set new localization programmatically.

To see all strings that should be localized, look inside PSPDFKit/PSPDFKit.bundle/en.lproj/PSPDFKit.strings. PSPDFKit uses NSLocale.preferredLanguages to determine the language and falls back to English if this method doesn't return anything or the language is not available either in the PSPDFKit.bundle or the language dictionary. PSPDFKit will not look into your default project strings file. To get all strings translated (including OS-level default buttons like "Edit" or "Done") you need to add a Localizable.strings file of your target language to your project.

1
2
3
4
5
6
PSPDFSetLocalizationDictionary([
    "en": [
        "Go to %@": "Browse %@",
        "%d of %d": "Page %d of %d"
    ]
])
1
2
3
4
5
6
PSPDFSetLocalizationDictionary(@{
    @"en": @{
        @"Go to %@": @"Browse %@",
        @"%d of %d": @"Page %d of %d"
    }
});

As a further option, you can also use PSPDFSetLocalizationBlock(NSString *(^)(NSString *stringToLocalize)) to register a block that is called every time a string is translated. This way you can easily use your default bundle or a custom bundle with NSLocalizedStringFromTableInBundle.

Copy
1
2
3
4
5
6
7
8
9
10
11
12
13
PSPDFSetLocalizationBlock { stringToLocalize in
    guard let stringToLocalize = stringToLocalize else { return nil }

    // This will look up strings in language/PSPDFKit.strings inside your resource folder.
    return NSLocalizedString(stringToLocalize, tableName: "PSPDFKit", comment: "")

    // You can also route translation through your default localization:
    return NSLocalizedString(stringToLocalize, comment: "")

    // Or use a custom variant, for example to test if everything is localized:
    // Please keep in mind that several strings like "Edit" are provided by the system and automatically translated, provided that you have the correct localization resources set.
    return String(format: "_____%@_____", arguments: [stringToLocalize])
}
Copy
1
2
3
4
5
6
7
8
9
10
11
PSPDFSetLocalizationBlock(^NSString *(NSString *stringToLocalize) {
    // This will look up strings in language/PSPDFKit.strings inside your resource folder.
    return NSLocalizedStringFromTable(stringToLocalize, @"PSPDFKit", nil);

    // You can also route translation through your default localization:
    return NSLocalizedString(stringToLocalize, nil);

    // Or use a custom variant, for example to test if everything is localized:
    // Please keep in mind that several strings like "Edit" are provided by the system and automatically translated, provided that you have the correct localization resources set.
    return [NSString stringWithFormat:@"_____%@_____", stringToLocalize];
});

Pluralization Considerations

Note: PSPDFKit both uses PSPDFKit.strings and PSPDFKit.stringsdict file. A stringsdict file is used to define language plural rules - some languages have more pluralization variants other than just one and many; see for example the pluralization rule for Croatian:

Copy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<key>%tu match(es) found</key>
<dict>
    <key>NSStringLocalizedFormatKey</key>
    <string>%#@tu_matches_found@</string>
    <key>tu_matches_found</key>
    <dict>
        <key>NSStringFormatSpecTypeKey</key>
        <string>NSStringPluralRuleType</string>
        <key>NSStringFormatValueTypeKey</key>
        <string>tu</string>
        <key>zero</key>
        <string>Nema pronađenih rezultata</string>
        <key>one</key>
        <string>%tu pronađen rezultat</string>
        <key>two</key>
        <string>%tu pronađena rezultata</string>
        <key>other</key>
        <string>%tu pronađenih rezultata</string>
    </dict>
</dict>

PSPDFLocalize() automatically looks in both the stringsdict and the classical strings file to look up localized strings.

Manually override localization

You can manually override the system defaults and force a specific language. We generally do not recommend this as it's against Apple HIG and the platform handles this system-wide very well. In case you have a use case that requires this, recreate all UI elements manually after updating the setting or - ideally - simply restart the application to update the localization. You can achieve this via either setting PSPDFSetLocalizationBlock and returning a custom language, or (better) change this system-wide via setting the AppleLanguages in the user defaults. This needs to happen very early, before your app initializes. You can place this in the main.m/Main.swift file before UIApplicationMain or simply use a function with a constructor attribute in an Objective-C file. See how this can be done in Swift here.

Copy
1
2
3
__attribute__((constructor)) static void PSCForceCustomLanguage(void) {
    [NSUserDefaults.standardUserDefaults setObject:@[@"de"] forKey:@"AppleLanguages"];
}

You can learn more about AppleLanguages in Apple's QA1391 article. If your app requires to update localization at runtime without restarting the app, you can do more advanced tricks like swizzling [NSBundle localizedStringForKey:value:table:].