Zendesk iOS SDK multilanguage support - ios

are there anyone familiar with Zendesk iOS SDK? I am trying to integrate this SDK to my iOS app and the integration was done really issue, the only problem I have currently is multi language support. My app have a view when you can change the language on the fly using this code:
NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:lang forKey:#"lang"];
[defaults synchronize];
It changes the lang in app successfully, but it is not changing for Zendesk View. How to change language for Zendesk Chat View also?
Thanks!

The answer would be to override ZDCChatStrings bundle with your custom class, and whenever it will call for localizedStringForKey method return translation from your internal translations list. Code:
#import "NSBundle+Language.h"
#import <UIKit/UIKit.h>
#import <objc/runtime.h>
#interface CustomBundle : NSBundle
#end
#implementation CustomBundle
- (NSString *)localizedStringForKey:(NSString *)key value:(NSString *)value
table:(NSString *)tableName
{
return NSLocalizedStringFromTable(key, g_appDelegate.lang, key);
}
#end
#implementation NSBundle (Language)
+ (void)registerBundle
{
static dispatch_once_t tempToken;
dispatch_once(&tempToken, ^{
NSBundle *bundle = [NSBundle bundleWithPath: [[NSBundle mainBundle] pathForResource: #"ZDCChatStrings" ofType: #"bundle"]];
object_setClass(bundle, [CustomBundle class]);
});
}
#end
Initialize somewhere in your AppDelegate:
[NSBundle registerBundle];

You need to change the Localizable string in ZenDesk Api Files not your custom file. But this is Internationalization. Language change according to your phone Language.
Goto Your Projects Supporting Files. There are ZDCChatStrings.bundle and ZDCChat.bundle are there. Open ZDCChatStrings.bundle. In this you see Localizable.strings for All languages.
Right click on strings files which you want and Open as Ascii Property List. Change strings accordingly.

Related

iOS - How to change app language in storyboard strings without programmatically?

I am developing an app in which an user can change language at any time. I have done this in a demo app. It is working fine. But there is an issue with it, that is for localisation app I have to do following 2 tasks.
Step 1: I have to create IB outlet for every object (i.e in every class ==> buttons, labels, textFields, TextViews).
Step 2 : I have to set language for every objects for example : [myButton setTitle:[Language get:#"Language Test" alter:nil] forState:UIControlStateNormal];
OR myLabel.text=LocalizedString(#"Forgot Passoword");
I have a project which has many screens, around 60 screens (in storyboard). Unfortunately in this project there is no IB outlet for all objects. Strings are set in via storyboard. Now I have to make support this app in another language also (current language english )name Arabic language.
Conclusion : If I do above 2 steps (create IB outlet for every objects
, then write code in .m file for every object). It will take very much
time. Is there any other better options please ? I want do not want
create IB outlet and coding in .m file. Any suggestion will be great!!
What I have done till now :
Follow these tuttorials :
(1). How to force NSLocalizedString to use a specific language
and sample projects :
(1). https://github.com/tonisalae/TSLanguageManager
(2). https://github.com/object2dot0/Advance-Localization-in-ios-apps
My code :
example calls:
[Language setLanguage:#"it"];
OR
[Language setLanguage:#"de"];
+(void)initialize {
NSUserDefaults* defs = [NSUserDefaults standardUserDefaults];
NSArray* languages = [defs objectForKey:#"AppleLanguages"];
NSString *current = [languages objectAtIndex:0];
[self setLanguage:current];
}
+(void)setLanguage:(NSString *)l {
NSLog(#"\n\n\t ***** Hint Lang. selected by user: %# ****\n\n", l);
NSString *path = [[ NSBundle mainBundle ] pathForResource:l ofType:#"lproj" ];
bundle = [NSBundle bundleWithPath:path];
}
+(NSString *)get:(NSString *)key alter:(NSString *)alternate {
return [bundle localizedStringForKey:key value:alternate table:nil];
}
You can achieve this using User Defined Runtime Attribute. Follow this link for detail.

Launch arguments (NSDoubleLocalizedStrings, NSShowNonLocalizedStrings) don't work

I'm trying to use the launch arguments such as NSDoubleLocalizedStrings and NSShowNonLocalizedStrings to test localization in my Objective-C project. For some reason I couldn't get neither of them to work. I tried to set both arguments on launch and options in scheme settings:
Also I've checked NSUserDefaults keys and they both are YES. But the arguments still don't work.
To make sure it's not an XCode bug I've created absolutely new single-view project on Objective-C and Swift with one label on the view. Both projects had empty Localizable.strings files and the code in these projects was the following:
#interface ViewController ()
#property (nonatomic, strong) IBOutlet UILabel *label;
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.label.text = NSLocalizedString(#"Some text", nil);
}
#end
and
class ViewController: UIViewController {
#IBOutlet var label: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
label.text = NSLocalizedString("Some text", comment: "")
}
}
The result looked like this:
So here are the questions:
1) What could be the reasons launch arguments don't work in my Objective-C project?
2) Why NSDoubleLocalizedStrings argument doesn't work in Swift?
Spending couple days on investigation and deleting gradually all the files and frameworks from my Objective-C project I figured out that the reason was in AFNetworking library. The issue is described here. If you want to use AFNetworking in your project and debug the localization issues you can add such lines to application: didFinishLaunchingWithOptions:
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setBool:YES forKey:#"NSDoubleLocalizedStrings"];
[defaults setBool:YES forKey:#"NSShowNonLocalizedStrings"];
[defaults synchronize];
On second launch of the app you’ll see those launch arguments working.
The answer for the second question about why NSDoubleLocalizedStrings argument doesn't work in Swift is that it's probably a bug in XCode. It might be connected with macros which are not supported in Swift, and NSLocalizedString is actually a macro. Therefore I've created a bug on radar.

Metaio SDK - Creating a new AR Application

I am following a tutorial on the Metaio website - Creating a New AR Application, and it seems to work (I get the Metaio splash screen, and the watermark shows up on the camera view when I build and run it on an ipad.
I'm trying to get the Hello World tutorial to work, using code directly copied from the Metaio SDK, but I am not able to get the model to appear over the racking image.
The implementation file code is below - I am getting no errors when I run it on an ipad, and get the camera view etc, but no 3d model - any suggestions? Thx:
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
- (void) viewDidLoad
{
[super viewDidLoad];
// load our tracking configuration
NSString* trackingDataFile = [[NSBundle mainBundle] pathForResource:#"TrackingData_MarkerlessFast"
ofType:#"xml"
inDirectory:#"Assets"];
if(trackingDataFile)
{
bool success = m_metaioSDK->setTrackingConfiguration([trackingDataFile UTF8String]);
if( !success)
NSLog(#"No success loading the tracking configuration");
}
// load content
NSString* metaioManModel = [[NSBundle mainBundle] pathForResource:#"metaioman"
ofType:#"md2"
inDirectory:#"Assets"];
if(metaioManModel)
{
metaio::IGeometry* theLoadedModel = m_metaioSDK->createGeometry([metaioManModel UTF8String]);
if( theLoadedModel )
{
// scale it a bit up
theLoadedModel->setScale(metaio::Vector3d(1.0,1.0,1.0));
}
else
{
NSLog(#"error, could not load %#", metaioManModel);
}
}
}
#end
Did you also use the xml tracking file, that should be in the assets folder?
As I see it, it could come from several errors:
- The tracking image doesn't have the same name in the xml file and in your folders
- the tracking file is empty or contains errors
Maybe you could share the xml tracking file as well so we could help you more.
Good luck

Programmatic language localisation without restart

I want to create an iPhone application with English and Arabic language. I checked the Internationalization document for language switcher, however to take that into effect I have to manually go and change the iPhone setting. I don't want to do that. So what I am planning is on home screen I will have two button as English and Arabic. If user click Arabic, I will have arabic text and if user select English, app will be in english.
Any idea/ suggestion how to get this done?
Note: I don't want to manually go and change the language.
Edit 1
As per #Jano, I have done below.
Created new project. Added Arabic in Localization. Now I have two storyboard and two InfoPlist.strings file.
Added Localization.h and .m file as shown in answer.
Directory structure is MyProject-ar.lproj & MyProject-en.lproj
Content of Plist are "myButton01" = "Back"; & "myButton01" = "ظهر";
First View Controller have two button as English and Arabic. Called action on those button.
- (IBAction)pressedEnglish:(id)sender {
[Localization sharedInstance].fallbackLanguage = #"ar";
[Localization sharedInstance].preferredLanguage = #"en";
NSLog(#"pressed english");
}
- (IBAction)pressedArabic:(id)sender {
[Localization sharedInstance].fallbackLanguage = #"en";
[Localization sharedInstance].preferredLanguage = #"ar";
NSLog(#"pressed arabic");
}
In second view controller, I added one button and gave name as myButton. Now in viewDidLoad, I have
[self.myButton setTitle:localize(#"myButton01") forState:UIControlStateNormal];
I hope this should be working, however when I run the project, I see button as myButton01
Any reason why this is happening?
Edit 2
I got Edit 1 problem. I renamed InfoPlist.strings to Localizable.strings and it worked. But but but, I am still getting Arabic text irrespective of whatever button I press.
When finding reason, I found that it was because of below statement that we have in Localization.m
static Localization *shared = nil;
dispatch_once(&pred, ^{
shared = [[Localization alloc] init];
shared.fallbackLanguage = #"en";
shared.preferredLanguage = #"ar";
The problem is at last two lines. As we have set Arabic as preferredLanguage, I am always seeing the arabic text.
What changes will I need to do so that I can have it as changeable as per button pressed.
You want to set the language of the app from the app UI ignoring the user preference on the device. This is unusual, but here you go...
First write all your language strings on a directory structure like this:
i18n/en.lproj/Localizable.strings
i18n/ar.lproj/Localizable.strings
Create an additional directory with the corresponding two letter code for each additional language supported.
If the files are recognized as i18n resources, they will be presented like this:
Files will have a key=value with the following format:
"button.back" = "ظهر";
In your code, replace any localizable string with the key. Example:
[self.stateBtn setTitle:localize(#"button.back") forState:UIControlStateNormal];
Usually you would use NSLocalizedString(#"key",#"fallback") but since you want to ignore iPhone settings, I wrote a localize(#"key") macro above that will have the following implementation:
Localization.h
#ifndef localize
#define localize(key) [[Localization sharedInstance] localizedStringForKey:key]
#endif
#interface Localization : NSObject
#property (nonatomic, retain) NSBundle* fallbackBundle;
#property (nonatomic, retain) NSBundle* preferredBundle;
#property (nonatomic, copy) NSString* fallbackLanguage;
#property (nonatomic, copy) NSString* preferredLanguage;
-(NSString*) localizedStringForKey:(NSString*)key;
-(NSString*) pathForFilename:(NSString*)filename type:(NSString*)type;
+(Localization*)sharedInstance;
#end
Localization.m
#import "Localization.h"
#implementation Localization
+(Localization *)sharedInstance
{
static dispatch_once_t pred;
static Localization *shared = nil;
dispatch_once(&pred, ^{
shared = [[Localization alloc] init];
[shared setPreferred:#"en" fallback:#"ar"];
});
return shared;
}
-(void) setPreferred:(NSString*)preferred fallback:(NSString*)fallback
{
self.fallbackLanguage = fallback;
self.preferredLanguage = preferred;
NSString *bundlePath = [[NSBundle mainBundle] pathForResource:#"Localizable" ofType:#"strings" inDirectory:nil forLocalization:self.fallbackLanguage];
self.fallbackBundle = [[NSBundle alloc] initWithPath:[bundlePath stringByDeletingLastPathComponent]];
bundlePath = [[NSBundle mainBundle] pathForResource:#"Localizable" ofType:#"strings" inDirectory:nil forLocalization:self.preferredLanguage];
self.preferredBundle = [[NSBundle alloc] initWithPath:[bundlePath stringByDeletingLastPathComponent]];
}
-(NSString*) pathForFilename:(NSString*)filename type:(NSString*)type
{
NSString *path = [self.preferredBundle pathForResource:filename ofType:type inDirectory:nil forLocalization:self.preferredLanguage];
if (!path) path = [self.fallbackBundle pathForResource:filename ofType:type inDirectory:nil forLocalization:self.fallbackLanguage];
if (!path) NSLog(#"Missing file: %#.%#", filename, type);
return path;
}
-(NSString*) localizedStringForKey:(NSString*)key
{
NSString* result = nil;
if (_preferredBundle!=nil) {
result = [_preferredBundle localizedStringForKey:key value:nil table:nil];
}
if (result == nil) {
result = [_fallbackBundle localizedStringForKey:key value:nil table:nil];
}
if (result == nil) {
result = key;
}
return result;
}
#end
This will use lookup the key strings in the arabic file, and if the key is missing, it will look in the arabic file. If you want it the other way, do the following from your button handlers:
[[Localization sharedInstance] setPreferred:#"ar" fallback:#"en"];
Sample project at Github.
If localisation doesn't work
If localisation doesn't work, use the plutil command line tool to verify the format of the file. It should output: Localizable.strings: OK. Example:
$ plutil -lint Localizable.strings
Localizable.strings: OK
This format is described in Internationalization Programming Topics > Localizing String Resources. You can optionally add // single-line or /* multi-line */ comments. For non latin languages it’s recommended to encode Localized.strings in UTF-16. You can convert between encodings in the inspector pane of XCode.
If it still doesn't work, check that you are copying the Localizable.strings file in the Copy files phase of your target. Note that when you add Localizable.strings files there, sometimes they appear in red, keep doing it until a file appears in black, then delete the red ones (hacky I know, blame Xcode).

Errors when trying to use CIKernel CoreImage/QuartzCore class on iOS

Hi I'm trying to use the CIKernel class
I don't understand why is it that I keep getting these errors:
AdriansFilter.m:23:29: error: receiver 'CIKernel' for class message is a forward declaration [4]
AdriansFilter.m:23:28:{23:28-23:62}: error: no known class method for selector 'kernelsWithString:' [4]
I've tried importing QuartzCore framework but it still doesn't work. I'm stuck because I really cannot determine what is the real issue here. Could somebody help me please?
my h file looks like this:
#import <Foundation/Foundation.h>
#import <QuartzCore/QuartzCore.h>
#interface AdriansFilter: CIFilter
{
CIImage *inputImage;
CIColor *inputColor;
NSNumber *inputDistance;
NSNumber *inputSlope;
}
#end
my m file looks like this
#import "AdriansFilter.h"
#implementation AdriansFilter
static CIKernel *hazeRemovalKernel = nil;
- (id)init
{
if(hazeRemovalKernel == nil)
{
NSBundle *bundle = [NSBundle bundleForClass: [self class]];
NSString *code = [NSString stringWithContentsOfFile: [bundle
pathForResource: #"MyHazeRemoval"
ofType: #"cikernel"]];
NSArray *kernels = [CIKernel kernelsWithString: code];
hazeRemovalKernel = [kernels objectAtIndex:0];
}
return [super init];
}
#end
You haven't imported a header where the interface for CIKernel is defined. By searching the Apple developer documentation, I don't find a CIKernel class reference for iOS. This suggests to me that the CIKernel class is not available on iOS.
In Xcode, click on CIKernel in your source file to put the text cursor there, then open the right column (also known as Utilities) of the Xcode window, then select the quick help inspector tab. If the selected class is available for iOS, you should see documentation for the class and a reference to which header file declares it. When I try this with the CIKernel class selected in an iOS project, I just get "No Quick Help".

Resources