I am currently working on my first small desktop menubar app (macOS, Swift 3). It needs to access
a) A list of words (Think word dictionary, 1k-5k words, per supported language)
b) A list of structured data (Think simple structs, ~500)
I am currently pondering, whether to build these in code - maybe a factory class per language. Or include them in my app as json and parse at runtime. Or maybe build an SQLite file and read that during runtime, although that approach would be harder to diff in source control ...
As I am new to the platform I was wondering whether there might be a better way that I am not aware of, or maybe performance considerations that render one of the mentioned approaches useless.
As usual, thanks in advance folks !
Your listed solutions can be used for this task. However I think for such kind of tasks the best solution is to use CoreData, where you can store a list of words as well as structured data, also make relations between them if you need it
I am about to implement a language system into my codeigniter project. (following this tutorial: http://www.sitepoint.com/multi-language-support-in-codeigniter/), but I am a bit stuck with the thinking process.
The website will contain alot of text so there would have to be alot of indivudual language files like error_english.php, user_english.php etc...
But I'm wondering, is that the right way to go? Like for example what if I have a page with different language files loaded in it because it has alot of text and I have to load 1 word, something like Firsname or something.
That would mean I'd have to load user_english.php while that will contain for example more than 100's rows of texts. Wouldn't there be alot of loading because of this, just for 1 word? There would be so many unneeded arrays.
Does anyone know a good design/routing pattern to be able to keep the server loadtime/performance as it's best?
language packs are simply key-value pairs. yes, you load thousands of lines if need be and it works fine. One way to mitigate that line count somewhat is to have different language pack files for different sections of site.
so you could have an error file and do:
$this->load->language('errors');
But really it doesn't make a practical difference for speed - it is an organisational thing.
I have extended mine to use field substitution. Language packs also provide a way to separate code from presentation - i always use them in models even if I am only writing in english because it forms a separation between code logic and outputs that makes the code easier to read.
so if you put this in your helpers:
function lang_sub( $str, $params = '')
{
$CI = & get_instance();
$return_string = $str;
if (array_key_exists($str, $CI->lang->language))
{
// the str is a key. so it only is a one line substitution.
$return_string = $CI->lang->line($str);
if (is_array($params))// if a parameter array is sent, substitute the strings %s in order.
{
$return_string = vsprintf($r, $params);
}
}
return $return_string;
}
you can do something like this in your language entry:
$lang['login_message'] = "Welcome %s good to see you again! we as last saw your on %s.";
and in your model can do something like:
$welcome_message = lang_sub('login_message',array($username,$last_seen));
note that it is a good idea to consider naming and collisions of your entries before you start.
good luck!
Looking fro some advise...
I'm creating a multi-language site with Codeigniter. CI allows me to create several language files, e.g. one per controller and load language files whenever I need them.
For me it sounds easier to just work with one language file and auto-load it, but this approach doesn't seem to be encouraged. Can anyone tell me if working with one language file (per language) is OK, or should I use a language file per controller ?
It depends on the size of your file, if size of your single file is too big then for every time you load the file all data for that file will get loaded and your script will take much more memory, in case of big language file it is always to use multiple files and load it when needed, and if your language file is small it is always better to use single file so that you don't need to manage it and simple to use.
Does Expression Engine have a built-in solution for i18n (internationalization)?
I have to build a multi-language site, and would like to know the best approaches in EE for doing so.
There are many ways you can create a multilingual or country-specific site in ExpressionEngine to deliver content specific to each language/country.
The two most popular solutions are summarized from the following ExpressionEngine Wiki articles:
MultiLingual Websites in ExpressionEngine
The basic idea is to present your content in different languages using a combination of URL Segments, custom fields and a bit of PHP.
Advantages
Single entry manages multiple languages
Simple URL structure
As an example, say you have a 3-language site: English (en), Spanish (es) and German (de).
For every piece of content in your site, you'd create a custom field with the language identifier as a postfix (or prefix, whatever you prefer) to the fields.
Your custom field names might look like this:
custom_field_en
custom_field_es
custom_field_de
To switch between languages, simply add a corresponding URL segment (/en, /es or /de) that matches the language:
example.com/template_group/template/en
example.com/template_group/template/es
example.com/template_group/template/de
The main advantage of this approach is that it keeps all versions of your content inside a single entry, making updates and edits easy and consistent.
MultiLingual Websites in ExpressionEngine, Alternative
The alternative approach idea is to create sub-directories for each country, and use ExpressionEngine's path.php Global Variables to hold the country code and/or language as a variable.
Advantages
No PHP needed
No need to keep track of which segment holds the language variable
Elegant URL structure
Using the same 3-languages as an example from the first method, you would create a new directory in the root of your EE install and name it after the country code of the language you want to add:
Your folder structure might look like this:
+ /de
+ /en
+ /es
index.php
+ /images
+ /system
+ /themes
To allow this method work, place a copy of the main index.php inside each of the language directories. You would then modify each file by assigning variables corresponding to each language's directory:
$assign_to_config['site_index'] = 'http://www.example.com/en/';
$assign_to_config['global_vars'] = array(
"country_code" => "en",
"language" => "english"
);
The URLs built will use whatever language/country designation you choose:
example.com/es-MX/template_group/template/
example.com/MX/template_group/template/
The main advantage of the alternative approach is using Global Variables, leveraging the fact they are are parsed very early, and can be used almost anywhere in templates.
See: ExpressionEngine's Parse Order (PDF, 33 KB)
Other Solutions
Embracing the philosophy of ExpressionEngine, the flexibility you're given as a designer/developer allows you to tailor a custom solution that suits your unique needs.
If either of these approaches don't quite meet your needs, you can eaily craft your own method or take a hybrid approach.
With this in mind, a good starting point would be to look into the Multilingual Add-Ons at Devot-ee that may aide in your development.
I am working on a Software Project that needs to be translated into 30 languages. This means that changing any string incurs into a relatively high cost. Additionally, translation does not happen overnight, because the translation package needs to be worked by different translators, so this might take a while.
Adding new features is cumbersome somehow. We can think up all the Strings that will be needed before we actually code the UI, but sometimes still we need to add new strings because of bug fixes or because of an oversight.
So the question is, how do you manage all this process? Any tips in how to ease the impact of translation in the software project? How to rule the strings, instead of having the strings rule you?
EDIT: We are using Java and all Strings are internationalized using Resource Bundles, so the problem is not the internationalization per-se, but the management of the strings.
I'm not sure the platform you're internationalizing in. I've written an answer before on the best way to il8n an application. See What do I need to know to globalize an asp.net application?
That said - managing the translations themselves is hard. The problem is that you'll be using the same piece of text across multiple pages. Your framework may not, however, support only having that piece of text in one file (resource files in asp.net, for instance, encourage you to have one resource file per language).
The way that we found to work with things was to have a central database repository of translations. We created a small .net application to import translations from resource files into that database and to export translations from that database to resource files. There is, thus, an additional step in the build process to build the resource files.
The other issue you're going to have is passing translations to your translation vendor and back. There are a couple ways for this - see if your translation vendor is willing to accept XML files and return properly formatted XML files. This is, really, one of the best ways, since it allows you to automate your import and export of translation files. Another alternative, if your vendor allows it, is to create a website to allow them to edit the translations.
In the end, your answer for translations will be the same for any other process that requires repetition and manual work. Automate, automate, automate. Automate every single thing that you can. Copy and paste is not your friend in this scenario.
Pootle is an webapp that allows to manage translation process over the web.
There are a number of major issues that need to be considered when internationalizing an application.
Not all strings are created equally. Depending upon the language, the length of a sentence can change significantly. In some languages, it can be half as long and in others it can be triple the length. Make sure to design your GUI widgets with enough space to handle strings that are larger than your English strings.
Translators are typically not programmers. Do not expect the translators to be able to read and maintain the correct file formats for resource files. You should setup a mechanism where you can transform the translated data round trip to your resource files from something like an spreadsheet. One possibility is to use XSL filters with Open Office, so that you can save to Resource files directly in a spreadsheet application. Also, translators or translation service companies may already have their own databases, so it is good to ask about what they use and write some tools to automate.
You will need to append data to strings - don't pretend that you will never have to or you will always be able to put the string at the end. Make sure that you have a string formatter setup for replacing placeholders in strings. Furthermore, make sure to document what are typical values that will be replaced for the translators. Remember, the order of the placeholders may change in different languages.
Name your i8n string variables something that reflects their meaning. Do you really want to be looking up numbers in a resource file to find out what is the contents of a given string. Developers depend on being able to read the string output in code for efficiency a lot more than they often realize.
Don't be afraid of code-generation. In my current project, I have written a small Java program that is called by ant that parses all of the keys of the default language (master) resource file and then maps the key to a constant defined in my localization class. See below. The lines in between the //---- comments is auto-generated. I run the generator every time I add a string.
public final class l7d {
...normal junk
/**
* Reference to the localized strings resource bundle.
*/
public static final ResourceBundle l7dBundle =
ResourceBundle.getBundle(BUNDLE_PATH);
//---- start l7d fields ----\
public static final String ERROR_AuthenticationException;
public static final String ERROR_cannot_find_algorithm;
public static final String ERROR_invalid_context;
...many more
//---- end l7d fields ----\
static {
//---- start setting l7d fields ----\
ERROR_AuthenticationException = l7dBundle.getString("ERROR_AuthenticationException");
ERROR_cannot_find_algorithm = l7dBundle.getString("ERROR_cannot_find_algorithm");
ERROR_invalid_context = l7dBundle.getString("ERROR_invalid_context");
...many more
//---- end setting l7d fields ----\
}
The approach above offers a few benefits.
Since your string key is now defined as a field, your IDE should support code completion for it. This will save you a lot of type. It get's really frustrating looking up every key name and fixing typos every time you want to print a string.
Someone please correct me if I am wrong. By loading all of the strings into memory at static instantiation (as in the example) will result in a quicker load time at the cost of additional memory usage. I have found the additional amount of memory used is negligible and worth the trade off.
The localised projects I've worked on had 'string freeze' dates. After this time, the only way strings were allowed to be changed was with permission from a very senior member of the project management team.
It isn't exactly a perfect solution, but it did enable us to put defects regarding strings on hold until the next release with a valid reason. Once the string freeze has occured you also have a valid reason to deny adding brand new features to the project on 'spur of the moment' decisions. And having the permission come from high up meant that middle managers would have no power to change specs on your :)
If available, use a database for this. Each string gets an id, and there is either a table for each language, or one table for all with the language in a column (depending on how the site is accessed the performance dictates which is better). This allows updates from translators without trying to manage code files and version control details. Further, it's almost trivial to run reports on what isn't translated, and keep track of what was an autotranslation (engine) vs a real human translation.
If no database, then I stick each language in a separate file so version control issues are reduced. But the structure is basically the same - each string has an id.
-Adam
Not only did we use a database instead of the vaunted resource files (I have never understood why people use something like that which is a pain to manage, when we have such good tools for dealing with databases), but we also avoided the need to tag things in the application (forgetting to tag controls with numbers in VB6 Forms was always a problem) by using reflection to identify the controls for translation. Then we use an XML file which translates the controls to the phrase IDs from the dictionary database.
Although the mapping file had to be managed, it could still be managed independent of the build process, and the translation of the application was actually possible by end-users who had rights in the database.
The solution we came up to so far is having a small application in Excel that reads all the property files, and then shows a matrix with all the translations (languages as headers, keys as rows). It is quite evident what is missing then. This is send to the translators. When it comes back, then the sheet can be processed to generate the same property bundles back again. So far it has eased the pain somewhat, but I wonder what else is around.
This google book - resource file management gives some good tips
You can use Resource File Management software to keep track of strings that have changed and control the workflow to get them translated - otherwise you end up in a mess of freezes and overbearing version control
Some tools that do this sort of thing - no connection an I haven't actually used them, just researching
http://www.sisulizer.com/
http://www.translationzone.com/en/products/
I put in a makefile target that finds all the .properties files and puts them in a zip file to send off to the translators. I offered to send them just diffs, but for some reason they want the whole bundle of files each time. I think they have their own system for tracking just differences, because they charge us based on how many strings have changed from one time to the next. When I get their delivery back, I manually diff all their files with the previous delivery to see if anything unexpected has changed - one time all the PT_BR (Brazillian Portuguese) strings changed, and it turns out they'd used a PT_PT (Portuguese Portuguese) translator for that batch in spite of the order for PT_BR.
In Java, internationalization is accomplished by moving the strings to resource bundles ... the translation process is still long and arduous, but at least it's separated from the process of producing the software, releasing service packs etc. One thing that helps is to have a CI system that repackages everything any time changes are made. We can have a new version tested and out in a matter of minutes whether it's a code change, new language pack or both.
For starters, I'd use default strings in case a translation is missing. For example, the English or Spanish value.
Secondly, you might want to consider a web app or something similar for your translators to use. This requires some resources upfront, but at least you won't need to send files around and it will be obvious for the translators which strings are new, etc.