Generating i18n property files dynamically from db - internationalization

I'd like to set up a simple server with a DB containing keys and translations for different messages. My different other applications would request this server, which would give them only the list of messages concerning them in, let's say, JSON. The different apps would then "compile" this list into several classic i18n .properties files they could use.
The advantage is that translation service is decorrelated from the different applications nofile has to be re-deployed or even updated on the applications servers. I could even set up a GUI to siplify operations on the messages.
Moreover, I found in the different projects I worked on that the manual maintenance of properties files can get really messy overtime (labels missing for one locale and it's really hard to find which one when the files get big, we used to use a central excel file to manage and generate .properties files but it's just a giant mess).
Anyway, do you think it's a good / feasable idea? Any insight on how to do it? How can I transform JSON into .properties easily? (is there tools for that?) (or should I use another format than JSON?). Thanks for any comment :)

To be blunt, I don't know why you want to reinvent the wheel and make it a bit more square-like.
Is it feasible? Yes it is.
Should you do it? No.
That is, you may serve translations with JSON, there is nothing wrong with that. It often makes sense.
What does not, is to put all the translations in a database. If you do that, I wish the localizers all the best.
It is just way easier to fix the translation in the standard text file (especially if it is UTF-8 encoded...) than in the database.
Talking about translations, you may want to (or be forced) to hire Translation Service Providers. These guys have there own Translation Memory systems as well as Machine Translation systems and guess what? They don't care about your database, nor GUI. They want to handle translations the standard way, that is using typical file formats. Java properties files happens to be one of them. Database scripts are not...
Now, on how to convert Java properties files to JSON. Assuming you are using Java, it's fairly straightforward. What you need first is to read your properties file:
// you somehow need to detect a Locale
ResourceBundle messages = ResourceBundle.getBundle("messages", locale);
The way you detect a Locale depends on the context. For instance, you may want to assign one in a user profile (allowing users to change their regional preferences), or you may want to create a web service that take language tag as a parameter. In both cases it would probably go down to this:
Locale locale = Locale.forLanguageTag(langTag);
Where langTag is a String containing your desired language tag (either read from user profile, which is recommended, or read as a parameter of a call to the web service).
When you have your resource file read, all you need to do is to take a desired portion and put it to the map:
Map<String, String> keyToTranslation = new HashMap<>();
for (String key : messages.keySet()) {
// filter the key somehow, for example:
// if (key.startsWith(moduleName))
keyToTranslation.put(key, messages.getString(key));
}
Then you can use Jackson to convert the map into JSON. Actually, any JAX-RS compatible library like RESTEasy would use it internally to perform the conversion.
It is of course possible to do this kind of conversion using completely different technology stack, i.e. using Node.js. However, there are few things to keep in mind:
Users may have a list of their preferred languages, which they advertise in a HTTP Accept-Language header. It is desirable to return a translation based on this list.
There is something called resource loading fallback. For instance, you may have no translations for Canadian version of French, but you may have regular French translations, which you may want to return to a user. ResourceBundle handles this for you, if you want to use something else, it is good to keep this in a back of your head.

You can use the i18n Maven Plugin to handle internationalization. It's very simple to configure your project. You render different output format files.
JSON
XML
Properties
Check out the sample i18n resource files.

Related

Localization of Domain Models in Neos / Flow

A website I am currently developing with Neos / Flow includes a self-developed shop system implemented as a Flow Plugin. The products, variants and vouchers are kept as domain models.
Since the customer wants to provide their website in different languages I need to find a way to manage translations for the domain objects.
I cannot find a way which is baked into Neos/Flow so my first thought was to simply insert translation identifiers inside the translatable fields (description & stuff like that) which are then used inside the view with the translation viewhelper. This would work totally fine if the customer would not want to edit those fields by themselves.
My next idea was to just implement an extra field for each language-dimension and each translatable field (like description_en; description_es, …). But this would be the worst approach in terms of maintainability and changeability.
I usually worked on TYPO3 projects where translation of domain objects is really easy and working out of the box. So this experience inside Neos is very frustrating.
Does anybody came across a similar problem or even has found a solution to this?
whenever we've got the requirement to have multi-language content so far, we've solved that, by storing the data within the Neos Content Repository. This way language handling aka dimensions work out of the box. Also, building a UI for that records is very easy by using inline editing or the inspector of the content module.
Note, that storing data in the CR does not necessarily means, that you have to store it under the /site root node. You could also add a new root node /products to store your products.
You could have a look at https://github.com/neos/metadata-contentrepositoryadapter where meta data is stored under its own root.
Hope that helps,
Cheers, Daniel
For the record, something like that could also be achieved with the Doctrine Translateable extension in pure Flow:
https://github.com/Atlantic18/DoctrineExtensions/blob/master/doc/translatable.md
See http://flowframework.readthedocs.io/en/stable/TheDefinitiveGuide/PartIII/Persistence.html#on-the-doctrine-event-system on how to activate the extension in Flow.
However, the cleaner aproach indeed is to actually separate domain model and content (unless you build a CMS and the content is your domain ;)

How to keep track of some user data without displaying it in the URL

I'm developing a web app with two languages, German and English. I have implemented searching on my webpage, and I want to keep track of the user's locale when searching.
How can I achieve this:
http://localhost:8080/user/search?search=pax?lang=de
instead of:
http://localhost:8080/user/search?search=pax
In my form I have:
action="/user/search"
I tried
action="<spring:message code="user.search.movie.link"/>
user.search.movie.link = /user/search or /user/search?lang=de
but it doesn't work.
Putting information in URL parameters is good in some cases*, but probably not this one. It seems likely that a user chooses their language setting once, around login time, and then rarely if ever changes it. Or it might even be set automatically. If so, language is something you might want to store in the user's session, or a persistent store like a database if you're using one. You seem to be using Spring, and I don't know a lot about their session handling, but their docs are at https://docs.spring.io/spring-session/docs/current/reference/html5/.
*: for more on this, you might want to read up on the differences between GET requests and POST requests (here's one of many SO posts on the topic). The most relevant part for you is that GETs are the ones that have visible parameters in the URL, but there are lots of other reasons to use one over the other.

Create a secret url using spring boot

I'm studying different technologies to create an API for a multi plateform application. This application has to give the possibility to users to share a file with a friend without authentication, but the URL has to be unguessable so the file keep secret. Juste like sharing picture feature in google photos.
Spring boot is one of the most interesting framework to create a multi plateform API, but I'm wondering if it's possible to create a secret and unguessable URL.
Thank you for your time.
To answer your question : you can organize your URLs path with some random hard-to-guess part (eg https://hostname/fileshare/Zak/myVideos/295223cb464d4e4794b93a09a1c730fd) UUIDs are 128 bits data and pretty much standard.
Another way would be to add a checksum token in the queryString :
https://hostname/fileshare/Zak/myVideos/lolcat.mp4?h=187515ZEDwhere the token is generated from the url path (and possibly even the queryString) with some secure algorithm (for exemple hmac256) and have your Controller (or better, a Filter) check if the h parameter is indeed equal to the hashed path.
EDIT : further explanation :
I'm assuming you've already got (or at least intend to have) a controller capable to serve content based on a file system directory. In my previous example, I assumed something of the likes /Zak/myVideos/. Spring controllers can easily return files in this directory by their filenames, but if the filename are easy to guess (eg video.mp4), I understand that /Zak/myVideos/video1.mp4 would be vulnerable. That's why I suggested to use UUIDs.
How to use UUIDS ?
If you can rename the files in /Zak/myVideos, simply rename them by random UUIDs and it will work transparently. The drawside to this is 1) the filenames won't mean anything anymore and 2) you're maybe not able to rename those files.
You can also have a DB table referencing filenames and UUIDs, and simply have your controller call a service to retrieve the correct filename from the correct UUID. The drawside to this is that you'd need to have a DB and write some code (and slow down API calls to query the DB).
That's why I also suggested to simply use a token. The url would still be the litteral path to your file, but require an additional parameter (the token) in the queryString. A servletRequestFilter could check whether the token is valid or not (with a simple hash + check algorithm) before granting access to the controller serving the file. This way, you won't need to rename your files nor create a DB.

MiniProfilerEF view results without RenderIncludes()

Is there another way to view the profiling results of MiniProfiler (I'm specifically interested in EF5 version)?
Every tutorial that I've seen uses MiniProfiler.RenderIncludes(); but since my MVC app mostly returns JSON, that is not an option for me.
Is there a way to write results to file or something like that?
You can read and write results to just about anywhere by changing the MiniProfiler.Settings.Storage to a different IStorage implementation from the default (which stores to http cache). If you wanted to, this could store to and read from a file pretty easily (you would have to write your own custom implementation for that).
The files served by RenderIncludes are the html templates for displaying the results and the script to retrieve the results from the server and render them on the client (all found here). But you are by no means obliged to use this mechanism. If you want to write your own logic for retrieving and displaying results, you should base this off of the logic found in MiniProfilerHandler.GetSingleProfilerResult. This function roughly performs the following (putting in the siginificant steps for your purposes):
Gets Id of next results to retrieve (through MiniProfiler.Settings.Storage.List())
Retrieves the actual results (MiniProfiler.Settings.Storage.Load(id))
Marks the results as viewed so that they wont be retrieved again (MiniProfiler.Settings.Storage.SetViewed(user, id))
Converts these to ResultsJson and returns it
With access to MiniProfiler.Settings.Storage, you should be able to retrieve, serve and consume the profile results in any way that you want. And if you are interested in using the RenderIncludes engine but want to mess around with the html/js being served, you can provide your own custom ui templates that will replace the default behavior.

What is the correct way to save data in forms

What is the standard convention to save data in textboxes and other form data to be loaded the next time the program is opened?
I personally do not know of any convention, however you could look into the following methods:
Using the registry: http://radio-weblogs.com/0111551/stories/2002/10/14/registryRwInC.html
Using profile strings: http://dotnet-snippets.com/dns/c-read-and-write-ini-files-SID574.aspx
Not sure of the standard convention, or if there is one, but saving to a text file would be a simple-to-implement solution.
It depends on the kind of data that you are trying to save. If this is a relatively small amount of user specific data associated with their user preferences, then user settings are the way to go.
If this is large amount of application data (for example like an entire address book), then you are probably better off writing to an external file or database in whatever format suits your needs.
You should be looking at Windows Forms data binding - that is the best way to save data from and reload data into a Windows Forms application. Once you have set up your form controls for data binding, you have a choice of where to store the data, as explained here.

Resources