semi-localization

Hi,
by “semi-localization” I mean this: suppose I have an app localized for English only: all controls show their own caption according to their relevant constant.
But I have a label that shows date.longdate, and running the app the label shows the longDate in my preferred language: English. So far so good.

Now I would like to have that label to show the longDate according to the user’s preferred language, for instance, Chinese, or Arabic and so on and so forth. As far as I know, this cannot be achieved, because the app is localized for English only.

Of course, if I added even just one constant localized for several languages and the user’s preferred language matched one of them, the System-supplied longDate would appear in the user’s preferred language. But the result of this, would be that on MAS the app would appear as localized for all the languages added in just one constant created as a mere placeholder (or language-holder). Too bad.

So, is there some declare (no plugin) that would let me achieve this result? More precisely: dates and times in the user’s preferred language…
I looked into macOSLib(64bit) but I find it difficult to detect a possible candidate method/function.

Thanks.

Carlo, I don’t know the answer to your question but thought of two alternatives:

1- Present the user with a settings window the first time the application is run and let them select their preferred format (or show a tooltip when the application is first opened, or… you get the idea)

2- Check the system locale (maybe macOSLib has something on this? or MBS?) and adapt the format yourself.

Julen

Hi Julien,

Yes, I have already built this step: the user will be asked either to keep date/time formats according to the English localization or to his/her preferred language; the preferred language being retrieved by macOSLib; for instance “ar” for arabic.

This is the issue I’m investigating and for which I asked for advice.
Adapting the format myself is more or less possible, provided I knew the name of months and of weekdays in all languages; but formats for unknown eastern languages would be tricky, at least.

Ideally I’d like something like:
label1.text = myDate.longDate(“ar”), or label1.text = myDate.longDate(systemDefault).

But as for now, it is just a dream…

Thank you.

Just musing: if it were not that the app is going to be sandboxed for MAS, an easy way would be to create a user’s preferredLanguage.lproj folder in Resources.
dim f as folderitem = specialfolder.Resources.child(“ar.lproj”)
if not f.exists then
f.createAsFolder
end if
Unfortunately once the app is sandboxed the Resources folder is no more available (not writable). How I love sandbox!

So back to square one, diving into macOSLib…

On this page UserGuide:Localization , there is an instruction Xojo.Core.Locale(langCode).
Maybe you can find some help here.

@Carlo Rubini — If you use LongDate to set a button’s caption, it will automatically use the System’s language, even if such language is not proposed by your application. I have just checked on my French macOS

@Stphane Mons: are you getting caption in the System’s language when running a built app?
Because I get it only when testing the app in the debugger.

@ThomasROBISSON : I use that approch in my apps; but it does not hold in this particular situation, since the app is not localized for all languages.

@Carlo Rubini — Then:

  1. MacOSLib’s NSLocale.currentLocale will give you the preferred language for the OS (the SystemLocale is a trap, don’t use it)
  2. Create a NSDateFormatter object and set its locale to the one from step 1
  3. Use the formatter StringFromDate method to convert a NSDate into a String

@Stphane Mons: Thank you for the suggestion. I’ll try it first thing next morning (here is already night).

@Stphane Mons : I tried to follow your instructions, and I hope you can spot something wrong in my code below, because, testing the built app, whatever preferred language I choose I always get its English rendering.

Again, I hope the fault is that I could not find the “StringFromDate method” you suggested. That’s way I first tried
mformatter.StringValue(mNSDate), but it returns no text;
while using mformatter.LocalizedString(mNSDate, etc.) it returns the right date although in English.

BTW: The code is in the action event of a button.

Added more code in [Edited] at the bottom.

[quote]MacOSLib’s NSLocale.currentLocale will give you the preferred language for the OS (the SystemLocale is a trap, don’t use it)
Create a NSDateFormatter object and set its locale to the one from step 1
Use the formatter StringFromDate method to convert a NSDate into a String[/quote]

//dim mCurrentLocale as Cocoa.NSLocale = Cocoa.NSLocale.SystemLocale dim mCurrentLocale as NSLocale = NSLocale.CurrentLocale dim mFormatter as new Cocoa.NSDateFormatter mFormatter.Locale = mCurrentLocale dim d as new date d.Year = 2001 d.Month = 9 d.day = 5 d.TotalSeconds = d.TotalSeconds dim mNSDate as new Cocoa.NSDate mNSDate = d//mNSDate.Now //MsgBox mformatter.StringValue(mNSDate)//always void string MsgBox mformatter.LocalizedString(mNSDate,Cocoa.NSDateFormatter.NSDateFormatterStyle.NSDateFormatterFullStyle, _ Cocoa.NSDateFormatter.NSDateFormatterStyle.NSDateFormatterFullStyle)

[Edited]
I forgot to mention that my first attempt was to use mformatter.LocalizedDateFormat, since it takes Locale as a parameter.
But I could not build the expected structured date-string:

dim myDate as string = d.longDate

Attempting to use NSDateComponents, I fail to see how to make a string from it.
'dim mDateComp as Cocoa.NSDateComponents
'mDateComp.Year = 2017
'mDateComp.Month = 11
'mDateComp.day = 05

MsgBox mformatter.LocalizedDateFormat(myDate, mCurrentLocale)//it returns garbage

Any idea how to proceed?
Thanks

@Carlo Rubini — The method you’re looking for is “StringValue”. You also need to change the formatter’s DateStyle value and TimeStyle if you want to display time as weel…

[code]dim formatter as new NSDateFormatter

formatter.Locale = NSLocale.CurrentLocale
formatter.DateStyle = NSDateFormatter.NSDateFormatterStyle.NSDateFormatterFullStyle
formatter.TimeStyle = NSDateFormatter.NSDateFormatterStyle.NSDateFormatterFullStyle

dim d as new NSDate( new Date )

MsgBox formatter.StringValue( d )[/code]

@Stphane Mons : Same as before: built app shows dates in English, even when launched with French as preferred language.
So it seems that the only way to get dates in French is a fr.lproj in Resources. But that (in MAS) would flag the app as localized for French also.

@Stephane Mons: The CurrentLocale line doesn’t make sense. This isn’t what Carlo wants.

@Carlo Rubini : the code from Stephane is the right idea. You need to set the locale to the one that you want.

@Beatrix Willius : [quote]You need to set the locale to the one that you want[/quote]

Problem is, for locale I find only two choices: CurrentLocale and SystemLocale. I looked for something where I could supply/add the preferredlanguage code; but I can’t find anything like that.

In MBS you have an identifier as parameter in the constructor: https://www.monkeybreadsoftware.net/currencydateandtimeformat-nslocalembs-method.shtml#2

[code]dim a(-1) as string = NSLocalembs.availableLocaleIdentifiers

// show all identifers:
dim s(-1) as string
s.Append “All available Locale Identifiers:”

dim c as Integer = UBound(a)

for i as Integer=0 to c
dim identifier as string=a(i)
s.Append identifier
next

MsgBox Join(s)

// now show the currency symbols:

redim s(-1)
s.Append “All Currency symbols:”

c = UBound(a)
for i as Integer=0 to c
dim identifier as string=a(i)
dim n as new NSLocaleMBS(identifier)
s.Append n.CurrencySymbol
next

MsgBox Join(s)[/code]

@Beatrix Willius : I had tried NSLocale.availableLocaleIdentifiers and CanonicalLocaleIdentifier and what not; but at the end I always fail to set the locale.
Still trying. Meantime, thank you for answering.

It seems I got it: using formatter.Locale = new NSLocale(LangCode) in place of formatter.Locale = NSLocale.CurrentLocale.
Where LangCode is the code of the preferred language (that I retrieve when the app opens).

Thank you Stephane and Beatrix.

[code]
dim formatter as new NSDateFormatter

//formatter.Locale = NSLocale.CurrentLocale
formatter.Locale = new NSLocale(LangCode)

formatter.DateStyle = NSDateFormatter.NSDateFormatterStyle.NSDateFormatterFullStyle
formatter.TimeStyle = NSDateFormatter.NSDateFormatterStyle.NSDateFormatterFullStyle

dim d as new NSDate( new Date )

MsgBox formatter.StringValue( d )[/code]

Carlo:
Usually, when a software change a Preference at Open time, it revert it back at Close (Quit) time.

I read this question since its beginning, but because I do not understand, I didn’t chime in.

The LR states:

Reports the date in the user’s long date format as a string based on the user’s locale and formatting even if the user’s locale is a Unicode-only locale.

This makes me more in the dark on why you have to do it by your own.

Of course, I checked on Date.LongDate ; what you use may be different.

@Emile Schwarz : Actually I’m under the impression that once upon a time, maybe before 64Bits and/or before Cocoa, not only during a debugging session, but even after building the app, we used to get date and time according to the user’s preferred language.
But I maybe wrong, and I don’t have a pre-cocoa environment to test it.

Anyway, as things stand today, I think that the description in LR should read something like:
Reports the date in the user’s long (short and abbreviated too) date format as a string based on one of the app’s localization-country: that is, as I said at the beginning: if the user’s preferred language matches one of the app’s localization-country, then he/she will get the right format, otherwise the localization at build-time takes over: in my case English even if I select French or any other language as preferred language.
The behavior described in LR, at present, happens only when debugging the app.
Or it may well be that my understanding of LR is wrong.

If in your application, the right format is wrong : it is a Xojo bug.

The user have the right format (or it changed to it long time ago).

However:
You have a solution, so, at open time, store the ‘then’ format, set the one you need, and at quit time, restore the original value.

HTH