Can I change the current application language in runtime?
I have 9 windows, maybe 200 labels in total. All labels set with dynamic constant where have english, spanish and italian language.
I need to change the language in runtime, not by system, but by user choose.
what’s the best solution? if it were possible to change the application’s language would already be all set.
I had read that post… There are best solutions?
I have set all labels in xojo IDE with #constants , and now I have to revise all the 200 labels via code?
It would be much more comfortable if there were a instruction like Xojo.Core.Locale.Current = “es” or
dim newLocale as new xojo.Core.Locale(“es-ES”)
Xojo.Core.Locale.Current = newLocale
I can’t set in xojo IDE in label title = #constant(lang), but only #constant
You need to do the necessary changes all yourself. Everything needs to be an observer of the language change and then you have to change all labels in the notification.
4 years ago I’ve made this for a customer… all texts were database-stored and a languages could be easily swapped during runtime. No system settings needed to be changed and it worked cross-platform…
On OS X you can get the dynamic constants defined in your project like this:
[code] Declare Function NSClassFromString Lib “Foundation” (aClassName As CFStringRef) As Ptr
Declare Function mainBundle Lib “Foundation” Selector “mainBundle” (NSBundleClass As Ptr) As Ptr
Declare Function bundleWithPath Lib “Foundation” Selector “bundleWithPath:” _
(NSBundleClass As Ptr, fullPath As CFStringRef) As Ptr
Declare Function pathForResource Lib “Foundation” Selector “pathForResource:ofType:” _
(NSBundle As Ptr, name As CFStringRef, extension As CFStringRef) As CFStringRef
Declare Function localizedStringForKey Lib “Foundation” Selector “localizedStringForKey:value:table:” _
(NSBundle As Ptr, key As CFStringRef, value As CFStringRef, tableName As CFStringRef) _
As CFStringRef
Dim bundleClassPtr As Ptr = NSClassFromString(“NSBundle”)
Dim mainBundlePtr As Ptr = mainBundle(bundleClassPtr)
Dim enBundlePath As String = pathForResource(mainBundlePtr, “en”, “lproj”)
Dim esBundlePath As String = pathForResource(mainBundlePtr, “es”, “lproj”)
Dim itBundlePath As String = pathForResource(mainBundlePtr, “it”, “lproj”)
Dim enBundlePtr As Ptr = bundleWithPath(bundleClassPtr, enBundlePath)
Dim esBundlePtr As Ptr = bundleWithPath(bundleClassPtr, esBundlePath)
Dim itBundlePtr As Ptr = bundleWithPath(bundleClassPtr, itBundlePath)
// A dynamic constant named “Test” in “Module1” with translations in three languages
Dim enTest As String = localizedStringForKey(enBundlePtr, “Module1.Test”, “Not found”, Nil)
Dim esTest As String = localizedStringForKey(esBundlePtr, “Module1.Test”, “Not found”, Nil)
Dim itTest As String = localizedStringForKey(itBundlePtr, “Module1.Test”, “Not found”, Nil)[/code]
Don’t know about Windows and Linux.
I have to write more code to remedy the problem. To ensure that everything works in both, windows and osx, I have to manually rewrite away all the labels via code. Then perhaps it is better to save the labels to a text file or in a database, but in this way lose all work done on Xojo (200 constants created), what are served? just for default language?
It would be much easier to set the default language via code instead to read the system. But Xojo still doesn’t allow it. I wonder if they never will…
[quote=282232:@Eli Ott]On OS X you can get the dynamic constants defined in your project like this:
Don’t know about Windows and Linux.[/quote]
See http://blog.xojo.com/2014/03/05/picking-a-language-at-runtime/
The declares are unnecessary
dim s as string = dynamicConstant( locale )
on all platforms
And you’ll probably never get this to all work right - at least on OS X.
While you can change UI elements in your app (labels, text, & even menu items text) the OS inserts others menu items and localizes them based on the USERS preferred locale - and you’ll probably not be able to alter those correctly.
I don’t know for what platform you need it but this is how I change languages on OSX.
https://dl.dropboxusercontent.com/u/609785/Xojo/Forum/ChangeLanguage.zip
I haven’t found a way to do it ‘runtime’ though. I’m not sure if that’s even possible. I either just quit the App so the user can restart it or give the option to relaunch it via Applescript in a little helper.
Under Windows either, it does not seem possible to change language dynamically without quitting the app.
This link discusses possibilities, I retained it because it lists an utility that seems able to switch per app.
http://superuser.com/questions/905522/how-to-launch-a-64-bit-program-with-a-different-locale-than-the-system-locale
[quote=282281:@Marco Hof][…] change languages on OSX.
[…]
I haven’t found a way to do it ‘runtime’ though. I’m not sure if that’s even possible.[/quote]
It is not possible on OS X at runtime (also not if you develop ion Obj-C or Swift). Unless you program it yourself.
The challange is “during runtime”. Current mechanisms in both Win/macOS do not support this you have to develop your own solution.
I have an app (mac and Win32) that changes languages during runtime (English to Bengali (or Italian to Bengali) and back again from Bengali to English/Italian. To do that, I just do what has already been pointed out by others, i.e. manually. I’d add that the app does not expect to quit and re-launch; just to swap languages.
First I change the menus’ texts, then --in the same way-- I set labels, buttons etc. to their expected constant.
Since you are dealing with roman script only, once you have swapped the constants your problem is finished. In my case, since Bengali fonts need different dimensions, I have also to reposition objects.
if pBangla then
FileMenu.Text = kFile("bn")
FileClose.text = kClose("bn")
fileSave.text = kSave("bn")
#if TargetMacOS
windowMinimize.text = kMinimize("bn")
windowZoom.text = kZoom("bn")
#endif
//all the other menus
else
FileMenu.Text = kfile//falls back to preferred language
FileClose.text = kClose
//all the other menus
end if
It’s difficult and quite impractical wanting to offer dynamic changes of the language while the app is running.
Just consider how often a user will need this. Once, probably. So, why not simply tell the user that he can change the language but then needs to restart the app instead of you trying to get it all working without a relaunch? You’re only wasting your time on developing something that no one really needs.
Also, when you enable several languages, you may need to re-arrange your controls to match the changing width. Einhugur once made a set of controls for this purpuse, which were even changeable without restarting the app, and I made a simpler version that’s described here: http://www.tempel.org/RB/Localization, chapter 4.1