L10N - How to add translated Strings not necessarily of UI elements? - codenameone

I would like to provide the option to switch between two languages in my mobile application. I have already saved a l10n bundle file in my src directory where the basic UI String elements are translated, e.g. "cancel", "ok", etc..
I would like to also add String objects that are part of user feedback, Form titles, etc.. How do I use the "Add property" of the designer tool in this case? Should I declare and initialize all related String objects as static fields?

Just use the key strings as usual and once you install the bundle into the UIManager it should seamlessly apply to all elements.
You should never use statically initialized fields for this since their lifecycle isn't clear. The app loads the resource in init(Object) and until that's called the app might not be running. The resource might be inaccessible.

Related

Grails 3 "show" view with Fields plugin 2.1.0-SNAPSHOT

Stuck at a trivial problem in Grails 3.1.5: Show the fields of a domain object, excluding one of them, including a transient property. Yes, this is my first Grails 3 project after many years with previous versions.
The generated show.gsp contains
<f:display bean="rfaPdffile"/>
This will include a field that may contain megabytes of XML. It should never be shown interactively. The display: false constraint is no longer in the docs, and seems to be silenty ignored.
Next I tried explicitly naming the fields:
<f:with bean="rfaPdffile">
<f:display property='fileName'/>
<f:display property='pageCount'/>
...
</f:with>
This version suprisingly displays the values without any markup whatsoever. Changing display to field,
<f:with bean="rfaPdffile">
<f:field property='fileName'/>
<f:field property='pageCount'/>
...
</f:with>
sort of works, but shows editable values. So does f:all.
In addition I tried adding other attributes to f:display: properties (like in f:table), except (like in f:all). I note in passing that those two attributes have different syntax for similar purposes.
In the Field plugin docs my use case is explicitly mentioned as a design goal. I must have missed something obvious.
My aim is to quickly throw together a prototype gui, postponing the details until later. Clues are greatly appreciated
If I understood you correctly, you want to have all bean properties included in the gsp but the one with the "megabytes of XML" should not be displayed to the user?
If that is the case you can do:
f:with bean="beanName"
f:field property="firstPropertyName"
f:field property="secondPropertyName"
And the one you don't wish to display:
g:hiddenField name="propertyName" value="${beanName.propertyName?}"
f:with
So list all the properties as f:field or f:display and put the one you don't wish to display in a g:hiddenField Grails tag
You can also try:
f:field property="propertyName"
widget-hidden="true"
but the Label is not hidden in this case.
Hope it helps
My own answer: "use the force, read the source". The f:display tag has two rather obvious bugs. I will submit a pull request as soon as I can.
Bugs aside, the documentation does not mention that the plugin may pick up the "scaffold" static property from the domain, if it has one. Its value should be a map. Its "exclude" key may define a list of property names (List of String) to be excluded. This probably works already for the "f:all" tag; bug correction is needed for the "f:display" tag.
My subjective impression is that the fields plugin is in a tight spot. It is intertwined with the Grails architecture, making it sensitive to changes in Grails internals. It is also required by the standard scaffolding plugin, making it very visible. Thus it needs constant attention from maintainers, a position not to be envied. Even now conventions for default constraints seem to have changed somewhere between Grails 3.0.9 and 3.1.7.
Performance of the fields plugin is sensitive to the total number of plugins in the app where it is used. It searches all plugins dynamically for templates.
For the wish list I would prefer stricter tag naming. The main tags should be verbs. There are two main actions, show and edit. For each action there are two main variants, single bean or multiple beans.
My answer is that at present (2 March 2017) there is no answer. I have searched the Net high and low. For the index (list) and create and edit views, the fields plugin works well enough. A certain field can be easily excluded from the create and edit views, relatively easily from the list view (by listing those that should show), and in no way I could find from the show view. This is such a common need that one would suspect it will be addressed soon. Also, easily showing derived values in the show view, like 'total' for an invoice. One can do that by adding an ordered list with a list item showing the value below the generated ordered list of values, but that is kind of a hack.
In some ways, the old way was easier. Yes, it generated long views, but they were generated and didn't have to be done by the programmer - just custom touches here and there.

Are there any tools for recording web browser events for seleniumn2?

I am looking for something very simple. It can use the Selenium IDE recording tool, but it does not allow me to pick what kind of locators I get.
I want to use:
driver.findElement(By.className(str))
to locate things. All I need is something which watches which UI elements on a web page get clicked and writes out the class attributes of those tags.
If I use the Selenium IDE recording (and export to the right type of thing), I get:
#Test
public void testNav() throws Exception {
driver.get(baseUrl + "/");
driver.findElement(By.name("3.1.1.5.1.1")).clear();
driver.findElement(By.name("3.1.1.5.1.1")).sendKeys("dan");
driver.findElement(By.name("3.1.1.5.1.5")).click();
driver.findElement(By.linkText("Products")).click();
driver.findElement(By.linkText("Categories")).click();
driver.findElement(By.linkText("Create a Category")).click();
driver.findElement(By.linkText("Cancel")).click();
driver.findElement(By.linkText("Products")).click();
driver.findElement(By.cssSelector("a.DisplayAdminProductsLink")).click();
driver.findElement(By.linkText("Product1")).click();
There are problems with this. First, it is not give me any By.className() calls. Why? Those first 3 calls will not help me. The framework I am using puts arbitrary things into the name. How can I get it to see the class attribute?
There actually are unique words in the class attribute of all of the above tags. I design my apps so that this is so. Yet it will not use them.
Earlier I asked:
Why is it doing a "driver.findElement().click()"? This is fragile and does not
end up working.
What I need is:
elt = driver.waitFor(By.className("c")); elt.click();
This will work reproducibly.....
I am considering to be removed from the question, as the findElement() code does work. You need to set a general time-out on the driver. It is not very obvious that this can be done, but it can.
So, continuing on....
I can go to the "Options" and change the order of the "Locator Builders" in eclipse. I can put "css" at the top. Then I get:
driver.findElement(By.cssSelector("input[name=\"3.1.1.5.1.1\"]")).clear();
driver.findElement(By.cssSelector("input[name=\"3.1.1.5.1.1\"]")).sendKeys("dan");
driver.findElement(By.cssSelector("input[name=\"3.1.1.5.1.5\"]")).click();
The tags are like:
<input class="form-control LoginUsernameField" ... />
But it does not see the class attribute.... Or I can do this manually.
Selenium looks for a unique identifier to identify elements in a webpage. classNames are a very less desired option for this purpose as they are generally not unique. Ids and names on the other hand are generally unique. This might be the reason why Selenium IDE is not selecting classNames and going for other identifiers.
Selenium IDE records user actions. You would have clicked on the element for Selenium IDE to identify it and that is why you are getting driver.findElement().click().
If you want to wait for element to wait you can try implicit wait.
When you want to use driver.findElement(By.className(str)), are you sure that there is one and only one element in the webpage that is associated with a className? If that is the case you can modify the webdriver code manually to use className.

How to translate role in Drupal?

If I want to translate the role to other language, how do I do it?
I can change that to other language as the default but I would like to use English so I don't have to deal with UTF8 issue in my code with Asian charactors.
if(in_array("administer nodes", $user->roles))
I have tried to find it from translation module but this seems not translatable as other text in Drupal.
So I'm assuming you've already tried using the t() or st() functions?
If that's so, you may need to try a client-side AJAX translation solution. One way you might do this is to create a vocabulary of terms (corresponding to the English role names), and have the Asian character translation as a secondary field. Then use views to create a view of this vocabulary, and create a lightweight module that:
1) loads a Drupal AJAX script on every page (or every page where role names might be utilized)
2) the script looks for a list of specified containers by id that you know will contain role names
3) searches the view you created for the English pattern, and replaces it in the container with any positive matches
Drupal API's example AJAX module
You could then expand the module/AJAX script to solve other similar translate fails on your site.

ExtJS MVC, dynamic loading and i18n

I would like to translate my ExtJS application in different languages. My issue is that I'm using ExtJS MVC framework, and most of my JS files are downloaded dynamically by the framework itself.
The ideal solution (that I thought of) would be to have an extra option in the Ext.Loader (or in my Ext.app.Application) that would define the language to use, and depending on this to automatically download such file as "a.MyClass.fr.js" after loading my "a.MyClass.js" (which would contain an Ext.apply, overriding my string resources). That's probably not available in the ExtJS framework at the moment.
The alternative solution I can see, is to perform a trick on the server-side. First, a cookie would be created on the client, to set to the language. On the server-side, I could catch all the requests to JS files, then if a cookie is set (='fr' for example), I'd combine the requested JS file (MyClass.js) with its i18n's friend (MyClass.fr.js) dynamically on the server and return the result. That would work, but it's really tricky because it implies other things (caching...).
Maybe the best way is to implement the first behavior I described in the ExtJS framework myself...
What do you think? I'm looking for a really clean and neat way of doing it! Thanks :)
I recently struggled with the same problem.
Finding a clean way to do this was quite a challenge - most alternatives were either..
1) Duplicate your code base per locale (WTH)
2) Download localized files overriding each of your components (Maintenance hell? What about the poor translators?)
3) Use/generate a static file containing translations and refer to it (All languages are downloaded? Extra build step to generate it? How do you keep them in synch?)
I tried to get the best of all worlds and ended up with a utility class responsible for:
1) Loading the ExtJS translation files (which basically apply overrides to extjs base components)
2) Loading a locale specific property resourcebundle (specifying which locale to load) from the server.
3) Prototyping String with a translate() method which queries the loaded store (containing the message bundle from the server) and returns the translation based on the value of the string.
This is the gist of things:
Bundle & prototyping:
localeStore.load({
callback : function(records, operation, success) {
// Define translation function (NB! Must be defined before any components which want to use it.)
function translate() {
var record = localeStore.getById(this.valueOf()) ;
if(record === null) {
alert('Missing translation for: ' + this.valueOf()); // Key is not found in the corresponding messages_<locale>.properties file.
return this.valueOf(); // Return key name as placeholder
} else {
var value = record.get('value');
}
return value;
}
String.prototype.translate = translate;
callback.call(); // call back to caller(app.js / Ext.Application), loading rest of application
}
});
As an example from a view:
this.copyButton = Ext.create('Ext.button.Button', {
disabled: true,
text: 'DOCUMENT_LIBRARY_MENU_COPYTO_BUTTON'.translate(),
action: 'openCopyDialog'
});
Bundle on the server (mesages_en.properties):
DOCUMENT_LIBRARY_MENU_COPYTO_BUTTON=Copy file
etc..
Pros:
No-fuss code, 'Your_key'.translate() makes it easy to read and aware that this is a localized string
None/little maintenance overhead (Keeping an override file for each locale? Jesus..)
You only load the locale you need - not the whole shabang.
If you really want to, you could even have your own translation for the ExtJS locale files in the same bundle.
You could write unit tests to ensure that all bundles contain the same keys, thus avoiding orphaned translations later
Cons:
Synchronous - the store must be loaded before your main app starts. I solved this by adding a callback from the utility class which was called once all texts were loaded.
No real-time population of texts.. though I didn't want to make my users overload the server either :P
So far my approach has worked out pretty well for my requirements.
Site load isn't noticeably slower and the bundles (containing ~200 keys/values per bundle) measure out at ~10kb during load.
There is currently no solution so I decided to create my own hack/addon on the Ext.Loader. I uploaded the code on GitHub: https://github.com/TigrouMeow/extjs-locale-loader. It's exactly what I needed and I really hope it will help others as well!
You should first complete your development phase and build your project or use ext-all.js file to I18s translate your UI
see: http://docs.sencha.com/ext-js/4-0/#!/example/locale/multi-lang.html
The appropriate language modifier script (/ext/local/ext-lang-xxx.js) needs to be loaded after ext is loaded (including dynamically loaded classes). In the example above, I would have probably used Ext.Loader.loadScriptFile but they eval a downloaded one directly. The only other thing is that your classes need to be built in different languages or you just use variables and reference the lang-specific variable file.
you could also use a variable in the Loader paths:
var lang='fr';
Loader
{
paths:
{
'Ext': '.',
'My': './src/my_own_folder'+'/'+lang
}

How do you build a multi-language web site?

A friend of mine is now building a web application with J2EE and Struts, and it's going to be prepared to display pages in several languages.
I was told that the best way to support a multi-language site is to use a properties file where you store all the strings of your pages, something like:
welcome.english = "Welcome!"
welcome.spanish = "¡Bienvenido!"
...
This solution is ok, but what happens if your site displays news or something like that (a blog)? I mean, content that is not static, that is updated often... The people that keep the site have to write every new entry in each supported language, and store each version of the entry in the database. The application loads only the entries in the user's chosen language.
How do you design the database to support this kind of implementation?
Thanks.
Warning: I'm not a java hacker, so YMMV but...
The problem with using a list of "properties" is that you need a lot of discipline. Every time you add a string that should be output to the user you will need to open your properties file, look to see if that string (or something roughly equivalent to it) is already in the file, and then go and add the new property if it isn't. On top of this, you'd have to hope the properties file was fairly human readable / editable if you wanted to give it to an external translation team to deal with.
The database based approach is useful for all your database based content. Ideally you want to make it easy to tie pieces of content together with their translations. It only really falls down for all the places you may want to output something that isn't out of a database (error messages etc.).
One fairly old technology which we find still works really well, is to use gettext. Gettext or some variant seems to be available for most languages and platforms. The basic premise is that you wrap your output in a special function call like so:
echo _("Please do not press this button again");
Then running the gettext tools over your source code will extract all the instances wrapped like that into a "po" file. This will contain entries such as:
#: myfolder/my.source:239
msgid "Please do not press this button again"
msgstr ""
And you can add your translation to the appropriate place:
#: myfolder/my.source:239
msgid "Please do not press this button again"
msgstr "s’il vous plaît ne pas appuyer sur le bouton ci-dessous à nouveau"
Subsequent runs of the gettext tools simply update your po files. You don't even need to extract the po file from your source. If you know you may want to translate your site down the line, then you can just use the format shown above (the underscored function) with all your output. If you don't provide a po file it will just return whatever you put in the quotes. gettext is designed to work with locales so the users locale is used to retrieve the appropriate po file. This makes it really easy to add new translations.
Gettext Pros
Doesn't get in your way while coding
Very easy to add translations
PO files can be compiled down for speed
There are libraries available for most languages / platforms
There are good cross platform tools for dealing with translations. It is actually possible to get your translation team set up with a tool such as poEdit to make it very easy for them to manage translation projects
Gettext Cons
Solves your site "furniture" needs, but you would usually still want a database based approach for your database driven content
For more info on gettext see this wikipedia page
They way I have designed the database before is to have an News-table containing basic info like NewsID (int), NewsPubDate (datetime), NewsAuthor (varchar/int) and then have a linked table NewsText that has these columns: NewsID(int), NewsText(text), NewsLanguageID(int). And at last you have a Language-table that has LanguageID(int) and LanguageName(varchar).
Then, when you want to show your users the news-page you do:
SELECT NewsText FROM News INNER JOIN NewsText ON News.NewsID = NewsText.NewsID
WHERE NewsText.NewsLanguageID = <<Session["UserLanguageID"]>>
That Session-bit is a local variable where you store the users language when they log in or enters the site for the first time.
Java web applications support internationalization using the java standard tag library.
You've really got 2 problems. Static content and dynamic content.
for static content you can use jstl. It uses java ResourceBundles to accomplish this. I managed to get a Databased backed bundle working with the help of this site.
The second problem is dynamic content.
To solve this problem you'll need to store the data so that you can retrieve different translations based on the user's Locale. (Locale includes Country and Language).
It's not trivial, but it is something you can do with a little planning up front.
#Auron
thats what we apply it to. Our apps are all PHP, but gettext has a long heritage.
Looks like there is a good Java implementation
Tag libraries are fine if you're using JSP, but you can also achieve I18N using a template-based technology such as FreeMarker.

Resources