Yii2 change locale formats - internationalization

I am migrating from Yii 1.x to Yii2.
In Yii 1.x you could define/change the localized formats in a file (sth like /app/i18n/en.php), where you could set all your desired formats, which you could later use.
Now in Yii2 this is gone?
I have 4 languages, each one has different settings. What am i supposed to do if I need a new formatting function?
E.g. I want to make a format for prices in a shop, in each lang differently
DE - 1.234,56
EN - 1,234.567
SK - 1234,5
CZ - 1 234,5678
So I create a new formatter function Yii::$app->formatter->asPrice(1234.567890).
Do I have to program a switch inside the function, and check for the language? That would be very inconvenient, and a lot of duplicity if I need more such functions. And if I had a new language later, I would have to adjust all such functions with a new case.
There must be a better solution. Any ideas?
UPDATE
I think you guys did not get my problem.. I know I can set the locale, and use the asDecimal or similar function. But the problem is that I cannot specifically customize the formatting options - it automatically takes the format defined in the intl PHP extension. I need the possiblity to specifically customize these formats. Maybe e.g. the default for EN is 2 decimals, but I need 3. Where can I set this?

In Yii2 official documentation:
You can use as below:
Yii::$app->formatter->locale = 'en-US';
echo Yii::$app->formatter->asDate('2014-01-01'); // output: January 1, 2014
Yii::$app->formatter->locale = 'de-DE';
echo Yii::$app->formatter->asDate('2014-01-01'); // output: 1. Januar 2014
Yii::$app->formatter->locale = 'ru-RU';
echo Yii::$app->formatter->asDate('2014-01-01'); // output: 1 января 2014 г.
So if you have table with language you can set locale there and in main layout define "Yii::$app->formatter->locale = $lang->locale" where $lang is object of Language model(class) matching current language.

Why dont you want to use asDecimal?
echo Yii::$app->formatter->asDecimal(1234.5678);
DE - 1.234,568
EN - 1,234.568
SK - 1 234,568
CZ - 1 234,568
Or you may try something like:
private $_priceDecimals = [ 'de_DE' => 2, 'en_EN' => 3, 'sk_SK' => 1, 'cz_CZ' => 4];
public function asPrice($value)
{
return $this->asDecimal(
$value,
isset($this->_priceDecimals[$this->locale]) ? $this->_priceDecimals[$this->locale] : null
);
}

Related

Arabic Date is not showing in Laravel using Carbon

i want to show date and days in Arabic format using Carbon. but it's showing in English.
Carbon::setlocale("ar");
echo Carbon::parse()->format('D d F Y');
Result: Sun 12 May 2019
Expected result:
it should show day and month in arabic.
You can use this package instead Date
This package contains language files for the following languages:
Albanian
Arabic
Azerbaijani
Bangla
Basque
Belarusian
Bosnian
And more!
Insatall
composer require jenssegers/date
Usage
use Jenssegers\Date\Date;
Date::setLocale('nl');
echo Date::now()->format('l j F Y H:i:s'); // zondag 28 april 2013 21:58:16
echo Date::parse('-1 day')->diffForHumans(); // 1 dag geleden
Change the config/app.php locale to your lang then apply this code:
or you can change app locale dynamically by:
app()->setLocale('ar');
Then
\Carbon\Carbon::now()->translatedFormat('l')
Or
\Carbon\Carbon::createFromDate($now->year, $now->month, $day)->translatedFormat('l')
and so on...
Carbon::setLocale() is only for the diffForHumans method, otherwise it uses the gloabl PHP Datetime locals. So if you want to use Arabic you have to call
setLocale(LC_TIME, $locale);
then use Carbon method formatlocalized()
Carbon\Carbon::now()->formatLocalized($format);
Note that PHP recognizes more than one Arabic locale so you'll have to choose one from this list
Just make sure you pick one that's installed on the server you're working on or the setLocale() method will fail and return false.
Import Carbon ( use Carbon\Carbon; ) In The Top Of Your Controller.
Use Carbon In Your Function Like This :
public function index()
{
Carbon::setLocale('ar');
// Your Code Here...
}
In Your View Use Date Like This:
<p>
{{ \Carbon\Carbon::parse($user->created_at)->translatedFormat('l j F Y H:i:s') }}
</p>

Laravel 5.1 translate an array pass to blade

I have this in my controller
public function editProfile(Request $request){
$question1 = Question::where('group',1)->lists('question', 'id');
$question2 = Question::where('group',2)->lists('question', 'id');
return view('user', compact(''question1', 'question2'));
}
$question = {\"1\":\"What is the first name of your best friend in high school?\",\"2\":\"What was the name of your first pet?\",\"3\":\"What was the first thing you learned to cook?\",\"4\":\"What was the first film you saw in the theater?\"}
$question2 = {\"5\":\"Where did you go the first time you flew on a plane?\",\"6\":\"What is the last name of your favorite elementary school teacher?\",\"7\":\"In What city or town does your nearest sibling live?\"}
I would like to translate the value in both question 1 and question 2 and pass it to user blade without changing the key, Any suggestions?
As specified at the localization doc, you need to populate a lang file with translation strings. So, let's say you want to show both Spanish and English strings. In this case you'd need to create two files: /resources/lang/en/messages.php and /resources/lang/es/messages.php. The content of one of those files would be somewhat like this:
<?php
// resources/lang/es/messages.php
return [
'welcome' => 'Bienvenido'
];
This way, you could access the strings in there with the following method: __('messages.welcome'), which would return the string for the language set on your config/app.php -- the default entry is en, by the way, but you can set it to whatever you want. The value in there will define which language will be chosen when selecting strings.
Another method to create translation strings is using the string itself as key, storing them in a JSON file instead of PHP. For example, the following translation string:
{
"I love programming.": "Me encanta programar."
}
would be accessible through this: __('I love programming.').
Having said that, you may solve your problem through the two methods presented above. You could store in your DB keywords for the questions instead of the whole text, and create translation for as many languages as you want. Also, you could keep the questions in your database and create translation strings for those questions. Finally, you'd need to iterate over the fetched entries and translate each one of them, or use some Collection helper to do the hard work for you, like transform or map.

(Sketchup C API) Set mm as units of newly created model?

I see that there is a way to get units SUModelGetUnits from the model. But no method to Set the units for the model/file.
So, is it possible to set the units?
If yes, what is the method or is there any other indirect way - such that the new file gets saved with "Millimeters" units?
Note:This question has been posted earlier as part of this thread http://sketchucation.com/forums/viewtopic.php?f=180%26amp;t=57909.
Since this is a different question from the original thread I have added it separately.
Yes, it is possible to set the units using the SketchUp C API. You just need to use the UnitsOptions options manager to set the LengthFormat and the LengthUnit.
The UnitsOptions/LengthFormat value for Decimal is 0.
The UnitsOptions/LengthUnit value for millimeters is 2.
Here's some sample code that sets these values:
// Get the options manager
SUOptionsManagerRef options_manager = SU_INVALID;
SUModelGetOptionsManager(my_model, &options_manager);
// Get the UnitsOptions options provider
SUOptionsProviderRef options_provider = SU_INVALID;
SUOptionsManagerGetOptionsProviderByName(options_manager, "UnitsOptions",
&options_provider);
// Make a new typed value with value for mm
SUTypedValueRef typed_value = SU_INVALID;
SUTypedValueCreate(&typed_value);
SUTypedValueSetInt32(typed_value, 2);
// Set the value for LengthFormat to Decimal
SUTypedValueSetInt32(typed_value, 0);
SUOptionsProviderSetValue(options_provider, "LengthFormat", typed_value);
// Set the value for LengthUnit to mm
SUTypedValueSetInt32(typed_value, 2);
SUOptionsProviderSetValue(options_provider, "LengthUnit", typed_value);
You can find the full documentation for options provider here, which includes the breakdown of the various options providers, options, and values available.
Hope this helps.
Paul

Date localization

Can anybody help me with date localization?
My code:
<?php echo date("j F", ($data->create_time)); ?>
And it returns:
1 January
I want to translate this output to Russian language:
1 Января
Yii provides robust i18n functionality through classes such as CDateFormatter and CLocale. You can get an instance of these classes for your application's current language with Yii::app()->getDateFormatter() and Yii::app()->getLocale(). Use these to format your date with a format string either taken straight from the current locale (good if it works for you) or by specifying a custom string:
$formatter = Yii::app()->getDateFormatter();
$format = Yii::app()->getLocale()->getDateFormat('medium'); // use built-in
$format = 'd MMMM'; // or use custom
echo $formatter->format($format, $data->create_time);
i didn't run this code but looks what you are looking for.
http://kr2.php.net/strftime
Udachi^^

How to make client side I18n with mustache.js

i have some static html files and want to change the static text inside with client side modification through mustache.js.
it seems that this was possible Twitter's mustache extension on github: https://github.com/bcherry/mustache.js
But lately the specific I18n extension has been removed or changed.
I imagine a solution where http:/server/static.html?lang=en loads mustache.js and a language JSON file based on the lang param data_en.json.
Then mustache replaces the {{tags}} with the data sent.
Can someone give me an example how to do this?
You can use lambdas along with some library like i18next or something else.
{{#i18n}}greeting{{/i18n}} {{name}}
And the data passed:
{
name: 'Mike',
i18n: function() {
return function(text, render) {
return render(i18n.t(text));
};
}
}
This solved the problem for me
I don't think Silent's answer really solves/explains the problem.
The real issue is you need to run Mustache twice (or use something else and then Mustache).
That is most i18n works as two step process like the following:
Render the i18n text with the given variables.
Render the HTML with the post rendered i18n text.
Option 1: Use Mustache partials
<p>{{> i18n.title}}</p>
{{#somelist}}{{> i18n.item}}{{/somelist}}
The data given to this mustache template might be:
{
"amount" : 10,
"somelist" : [ "description" : "poop" ]
}
Then you would store all your i18n templates/messages as a massive JSON object of mustache templates on the server:
Below is the "en" translations:
{
"title" : "You have {{amount}} fart(s) left",
"item" : "Smells like {{description}}"
}
Now there is a rather big problem with this approach in that Mustache has no logic so handling things like pluralization gets messy.
The other issue is that performance might be bad doing so many partial loads (maybe not).
Option 2: Let the Server's i18n do the work.
Another option is to let the server do the first pass of expansion (step 1).
Java does have lots of options for i18n expansion I assume other languages do as well.
Whats rather annoying about this solution is that you will have to load your model twice. Once with the regular model and second time with the expanded i18n templates. This is rather annoying as you will have to know exactly which i18n expansions/templates to expand and put in the model (otherwise you would have to expand all the i18n templates). In other words your going to get some nice violations of DRY.
One way around the previous problem is pre-processing the mustache templates.
My answer is based on developingo's. He's answer is very great I'll just add the possibility to use mustache tags in the message keycode. It is really needed if you want to be able the get messages according to the current mustache state or in loops
It's base on a simple double rendering
info.i18n = function(){
return function(text, render){
var code = render(text); //Render first to get all variable name codes set
var value = i18n.t(code)
return render(value); //then render the messages
}
}
Thus performances aren't hit because of mustache operating on a very small string.
Here a little example :
Json data :
array :
[
{ name : "banana"},
{ name : "cucomber" }
]
Mustache template :
{{#array}}
{{#i18n}}description_{{name}}{{/i18n}}
{{/array}}
Messages
description_banana = "{{name}} is yellow"
description_cucomber = "{{name}} is green"
The result is :
banana is yellow
cucomber is green
Plurals
[Edit] : As asked in the comment follows an example with pseudo-code of plural handling for english and french language. Its a very simple and not tested example but it gives you a hint.
description_banana = "{{#plurable}}a {{name}} is{{/plurable}} green" (Adjectives not getting "s" in plurals)
description_banana = "{{#plurable}}Une {{name}} est verte{{/plurable}}" (Adjectives getting an "s" in plural, so englobing the adjective as well)
info.plurable = function()
{
//Check if needs plural
//Parse each word with a space separation
//Add an s at the end of each word except ones from a map of common exceptions such as "a"=>"/*nothing*/", "is"=>"are" and for french "est"=>"sont", "une" => "des"
//This map/function is specific to each language and should be expanded at need.
}
This is quite simple and pretty straightforward.
First, you will need to add code to determine the Query String lang. For this, I use snippet taken from answer here.
function getParameterByName(name) {
var match = RegExp('[?&]' + name + '=([^&]*)')
.exec(window.location.search);
return match && decodeURIComponent(match[1].replace(/\+/g, ' '));
}
And then, I use jQuery to handle ajax and onReady state processing:
$(document).ready(function(){
var possibleLang = ['en', 'id'];
var currentLang = getParameterByName("lang");
console.log("parameter lang: " + currentLang);
console.log("possible lang: " + (jQuery.inArray(currentLang, possibleLang)));
if(jQuery.inArray(currentLang, possibleLang) > -1){
console.log("fetching AJAX");
var request = jQuery.ajax({
processData: false,
cache: false,
url: "data_" + currentLang + ".json"
});
console.log("done AJAX");
request.done(function(data){
console.log("got data: " + data);
var output = Mustache.render("<h1>{{title}}</h1><div id='content'>{{content}}</div>", data);
console.log("output: " + output);
$("#output").append(output);
});
request.fail(function(xhr, textStatus){
console.log("error: " + textStatus);
});
}
});
For this answer, I try to use simple JSON data:
{"title": "this is title", "content": "this is english content"}
Get this GIST for complete HTML answer.
Make sure to remember that other languages are significantly different from EN.
In FR and ES, adjectives come after the noun. "green beans" becomes "haricots verts" (beans green) in FR, so if you're plugging in variables, your translated templates must have the variables in reverse order. So for instance, printf won't work cuz the arguments can't change order. This is why you use named variables as in Option 1 above, and translated templates in whole sentences and paragraphs, rather than concatenating phrases.
Your data needs to also be translated, so the word 'poop', which came from data - somehow that has to be translated. Different languages do plurals differently, as does english, as in tooth/teeth, foot/feet, etc. EN also has glasses and pants that are always plural. Other languages similarly have exceptions and strange idoms. In the UK, IBM 'are' at the trade show whereas in in the US, IBM 'is' at the trade show. Russian has several different rules for plurals depending on if they are people, animals, long narrow objects, etc. In other countries, thousands separators are spaces, dots, or apostrophes, and in some cases don't work by 3 digits: 4 in Japan, inconsistently in India.
Be content with mediocre language support; it's just too much work.
And don't confuse changing language with changing country - Switzerland, Belgium and Canada also have FR speakers, not to mention Tahiti, Haiti and Chad. Austria speaks DE, Aruba speaks NL, and Macao speaks PT.

Resources