26

I use base internationalization in xCode to manage multiple languages in my app.

In a xib file I've got this object :

Xrj-9E-2VK it's an UITextView

In the corresponding strings file :

"Xrj-9E-2VK.text" = "text translated in french"

But my text is still in English.

Any Suggestion ?

rmaddy
  • 314,917
  • 42
  • 532
  • 579
Jean Lebrument
  • 5,079
  • 8
  • 33
  • 67

12 Answers12

12

I've found the following workaround until Apple fixes this (serious) bug that still exists in iOS 7 :

You actually need to 'mix' the 'base localisation method' (= preferred method for Xcode 5 & iOS 7) with the 'older' method of using the 'Localizable.strings' file

1) create the file 'Localizable.strings' (File -> New -> iOS -> resource -> .strings file)

2) use Xcode to create localised versions of this file for each language you use (select the file 'Localizable.strings', in File Inspector under 'Localization' click on the selection button next to each language you use).

3) in your viewController create an IBOutlet @property for the UITextField :

@property (weak, nonatomic) IBOutlet UITextView *localizedTextView;

4) under 'viewDidLoad' add the following code :

self.localizedTextView.text = NSLocalizedString(@"textFieldKey", @"comment for the translator");

5) in each 'Localizable.strings' file add :

"textFieldKey" = "the translated text you want to be put in the textField";

That should do it !

Keep in mind that Apple will probably fix this bug somewhere in the near future, in that case the translation will be taken from the 'base localised storyboard' (the one with the object references in, like "a8N-K9-eJb.text" = "some translated text". In that case you can delete the 'Localization.strings' file, and use base localisation again for a UITextField

Ronny Webers
  • 5,244
  • 4
  • 28
  • 24
  • I want to complete your answer and mention that `base localisation` method and 'older' method of using the `Localizable.strings` is a mutually complementary. `Localizable.strings` files is used for in code strings such as alerts and etc. etc. – Dima Deplov Apr 17 '14 at 21:59
  • Wow, it's May and Apple still haven't fixed this. – Nestor May 26 '14 at 13:26
  • You can simply use `NSLocalizedStringFromTable` and save the trouble of moving the strings to Localizable.strings. – samwize Jun 17 '14 at 07:14
  • This does not seem to work somehow, see my answer for a workaround – Gabriel Cartier Jul 15 '14 at 14:56
  • Hello Gabriel Cartier, I must say that this method is working in my 2 Apps which are in the App Store since 15 months, even after my recent update using the latest XCode 6 and iOS 8. The app works perfectly in 2 languages. Not sure what you did differently? Can you clarify what did not work? – Ronny Webers Feb 11 '15 at 09:37
  • See my answer. You can't change the a UITextView with setText unless your textview is not an attributed text. In which case, you need to use the setAttributedText method. The answer suggests that you simply need to set the text which most of the time wouldn't work because using UITextView, in my opinion, seems to be mainly for attributed text. – Gabriel Cartier Feb 11 '15 at 16:48
  • 3
    Two years passed, iOS 7, 8 and 9 and the bug is still there. Apple don't give a crap. – Duck Jun 07 '16 at 16:27
  • Seven years later, still there. – lukemmtt Jun 24 '21 at 11:35
7

This still appears under Xcode 6 & IOS 8, and the previous answers don't satisfy me.

Here's my simple and quick workaround :

  1. Select the XIB and then in the file inspector
  2. Below "Localization", find the language that does not work
  3. Change "Localizable Strings" to "Interface Builder Cocoa Touch XIB"

XCODE XIB inspector file screenshot

  1. Run the app, the translation should be ok now !

You can then go back to "Localizable Strings" if you prefer... In this case please note that you must run at least once the app with the "Interface Builder Cocoa Touch XIB." option selected.

Macistador
  • 854
  • 12
  • 23
  • Thank you, this has worked for me in Xcode 6.1.1 and iOS 8.1. – svintus Jan 17 '15 at 02:35
  • Works for me until I clean the build target and build again... Had to fall back to regular localization :/ It's ridiculous that this bug still exists after so long. – Nailer Apr 07 '15 at 11:04
  • You rock dude! After hours, this fixed my problem. – alejandrormz Jun 03 '15 at 00:37
  • 4
    This isn't a real fix. It's working because the translated XIB is sticking around in your deployed copy of the app on the device and iOS is favoring it over the strings file. If you delete the app from the device and clean your workspace it will be broken again (which is what happens when you archive your app for the app store). – Michael Merickel Sep 16 '15 at 16:09
  • This is working great. But to make this fix last, you should not switch back to "Localizable Strings" but stick with the xib. – mad_manny Nov 24 '15 at 10:31
  • Very Bad Fix, It removed all Translations i entered before. – Intsab Haider Feb 28 '20 at 21:41
6

You can use NSLocalizedStringFromTable to retrieve the texts as generated by xcode's IB as follows, in viewDidLoad:

self.intro_text.text = NSLocalizedStringFromTable(@"2Vy-59-WN8.text", @"Main", @"");

Where 2Vy-59-WN8.text is the generated key you can find in the Main.strings for the UITextView.

BTW: this is an xcode/IB bug, not an iOS bug.

RickJansen
  • 1,615
  • 18
  • 24
  • I don't recommend hardcoding the text via hardcoded id generated by interface builder, it could change. You are better off extracting the base string and setting it via NSLocalizedString. – Kris Gellci May 30 '23 at 20:29
4

If you want to use the existing MainStoryboard.strings file you can programmatically assign the text of your textview using localizedStringForKey:value:table: like this

[[NSBundle mainBundle] localizedStringForKey:@"abc-12-3ba.text" value:@"" table:@"MainStoryboard"]

Doug Voss
  • 1,012
  • 1
  • 14
  • 11
2

This is my Swift 2 answer:

We don't want to repeat the fix in each UIViewController, so let's start with an extension:

import UIKit

extension UIViewController {

    // if the property "Selectable" = NO it will reset the font and fontcolor when setText is used.
    // So turn Selectable ON 
    func localizeUITextViewsFromStoryboard(storyboardName: String) {
        for view in self.view.subviews {
            if let textView = view as? UITextView,
                let restorationIdentifier = textView.restorationIdentifier {
                let key = "\(restorationIdentifier).text"
                let localizedText = NSLocalizedString(key, tableName: storyboardName, comment: "")
                if localizedText != key {
                    textView.text = localizedText
                }

            }
        }
    }

}

In each UIViewController where we need this fix, we write

override func viewDidLoad() {
    super.viewDidLoad()
    self.localizeUITextViewsFromStoryboard("Main")
}

This code uses the restoration ID of the UITextViews. This means the we need to copy the Object ID to the restoration identifier in the storyboard for each UITextView.

Gerd Castan
  • 6,275
  • 3
  • 44
  • 89
1

I got this to work with Xcode 5.1.1 and iOS7.

Select the ViewController you want to localize in the left file panel. In the right panel select the File Inspector.

You will see a "Localize..." button. Tap the button. You will be presented with a drop down list of languages you can select from. Select Base and then tap "Localize".

In the right panel the Localization section will now have "Base" selected and your other languages will be listed. Select the languages you want to support. Leave the "native" language of your app unchecked.

There are definitely caching issues. I have found that changes only appear sometimes after I have deleted the app from simulator and when I delete Xcode's derived data.

mick80234
  • 897
  • 8
  • 9
1

File a bug with Apple. Let them know this is happening, and causing you (and me) time and frustration. This whole localization system is not there to have us fall back to NSLocalizedString..

RickJansen
  • 1,615
  • 18
  • 24
0

UPDATE

The best way to actually change the text is to directly use the setter from the UITextView.

If your text is NOT formatted, simply use:

[textView setText:NSLocalizedString(key, comment)];

If your text IS formatted, you have to use:

[textView setAttributedText:[[NSMutableAttributedString alloc] initWithString:NSLocalizedString(key, comment)]];

You don't need to use the workaround anymore with the updated method.

WORKARROUND

To be able to achieve this, the easiest solution I have found is to simply add an extra UITextView with the translated text exactly at the same place as the other and hide it.

To display the proper view I do this in the viewDidLoad method of the controller:

NSString *language = [[NSLocale preferredLanguages] firstObject];
if ([language isEqualToString:FRENCH_LANGUAGE]) { //@"fr"
    UITextView.hidden = YES;
    UITextViewFR.hidden = NO;
}

Although this solution is definitely not elegant, it's certainly a good workaround when you don't have to keep a lot of translations.

That being said, using the storyboard localized string is not working. Adding an IBOutlet and setting the text attribute with a NSLocalizedString was not working too. I have looked around for a solution and it seems like no one has really been able to find a clear answer for that one.

Gabriel Cartier
  • 1,734
  • 20
  • 22
  • Technically, there is no way this solution does not work, you have two views and hide one based on the locale. Either validate that you go in the IF based on the locale or don't. – Gabriel Cartier Dec 11 '14 at 17:20
  • I agree that technicaly this could work, but what would you do if you need to support 20 languages? you'd need to modify your code each time you add a language. Try setting up autolayout with 20 textViews layered on top of each other, it will be a nightmare. The whole purpose of decouping translations from your view is gone if you go this way. I would not recommend it. Translations should be completely decoupled from your UI – Ronny Webers Feb 11 '15 at 09:39
  • Yea I mentioned that it was actually not a viable solution. I had updated my post too, with the method `[textView setAttributedText:[[NSMutableAttributedString alloc] initWithString:NSLocalizedString(key, comment)]];` it is actually fairly simple. The problem is that the accepted answer does not work since a long time ago. – Gabriel Cartier Feb 11 '15 at 16:43
0

Xcode 7 still seems buggy...

Before trying anything complicated try these 3 simple steps:

  1. Delete the app from the device (not the simulator)
  2. Product -> Clean
  3. Run on device

Good luck.

tdeegan
  • 436
  • 3
  • 10
0

This issue still occurs in Xcode 11.5. I have decided to use UILabel instead and the localised text is being picked up as expected. This is an easy workaround when you keep static text in the view. Just remember to set maxLines to a higher number.

tomi44g
  • 3,266
  • 1
  • 20
  • 28
0

I finally found the reason. there was missing semicolon character one of the lines. I've putted that semicolon and problem fixed

Ufuk Ugur
  • 186
  • 1
  • 17
-1

XIB files do not have their own ".strings" files. You can generate ".strings" from XIB using ibtool, then after translation you use ibtool again to embed the translations into the localized XIB.

If you still have only one English XIB, you need to create a French XIB using Xcode, then do the ibtool process.

Take a look here: https://developer.apple.com/library/ios/documentation/MacOSX/Conceptual/BPInternational/Articles/LocalizingInterfaces.html

HyBRiD
  • 688
  • 4
  • 23
  • When I used base internationalization I specified for French language all my XIB files. xCode create for each XIB file a file .string corresponding. So I don't have to use ibtool ? – Jean Lebrument Oct 17 '13 at 14:45
  • You're right, I forgot about Base Internationalization. Note that this feature only works when building for iOS 6.0 or greater (iOS deployment target). What is your iOS deployment target? – HyBRiD Oct 20 '13 at 12:12