{"id":7089,"date":"2015-10-04T22:41:27","date_gmt":"2015-10-05T02:41:27","guid":{"rendered":"http:\/\/www.useragentman.com\/blog\/?p=7089"},"modified":"2015-10-04T23:29:46","modified_gmt":"2015-10-05T03:29:46","slug":"fixing-badly-formatted-properties-files-and-using-libreoffice-excel-to-make-them-translator-friendly","status":"publish","type":"post","link":"http:\/\/www.useragentman.com\/blog\/2015\/10\/04\/fixing-badly-formatted-properties-files-and-using-libreoffice-excel-to-make-them-translator-friendly\/","title":{"rendered":"Fixing Badly Formatted .properties Files and Using LibreOffice\/Excel to Make Them Translator Friendly."},"content":{"rendered":"\r\n<div class=\"image-container\"><img decoding=\"async\" src=\"https:\/\/www.useragentman.com\/blog\/wp-content\/uploads\/2015\/10\/manure-pit.jpg\" alt=\"manure-pit\" class=\"alignnone size-full wp-image-7106 full-bleed\" \/><div class=\"caption\">Image Credit, <a href=\"https:\/\/www.flickr.com\/photos\/boni_face\/502490160\/\">boni_face<\/a><\/div>\r\n<\/div>\r\n<p>For those unfamiliar with them, <strong><a href=\"https:\/\/en.wikipedia.org\/wiki\/.properties\"><code>.properties<\/code> files<\/a> are configuration files for Java.<\/strong>  Among other things, one of their major uses are multi-language support in JSP pages. They are, however, not just restricted to Java &mdash; <strong>libraries exist for <a href=\"https:\/\/github.com\/jquery-i18n-properties\/jquery-i18n-properties\">JavaScript<\/a>, <a href=\"https:\/\/github.com\/jnbt\/java-properties\">Ruby<\/a>, <a href=\"http:\/\/search.cpan.org\/~salva\/Config-Properties-1.75\/lib\/Config\/Properties.pm\">Perl<\/a>, <a href=\"https:\/\/flex.apache.org\/asdoc\/mx\/resources\/IResourceBundle.html\">Flex<\/a> and a whole slew of other languages.<\/strong><\/p>\n<p>So many times, in my many dives into the Java world, I come across badly managed <code>.properties<\/code> files.  In a mulit-developer shop, things quickly change from this:<\/p>\n<blockquote class=\"code\">\n<pre>\r\naccount.security.check = V\u00e9rification de s\u00e9curit\u00e9\r\naccount.not.available = Pas s\u00e9lectionn\u00e9\r\naccount.confirmation.password.updated = Votre mot de passe a \u00e9t\u00e9 mis \u00e0 jour.\r\nsearch.empty.message = Nous n\u2019avons pas trouv\u00e9 de r\u00e9sultats pour {0}\r\n<\/pre>\n<\/blockquote>\n<p>to this:<\/p>\n<blockquote class=\"code\">\n<pre>\r\naccount.security.check                 = V\\u00e9rification de s\\u00e9curit\\u00e9\r\naccount.not.available=        Pas s&amp;eacute;lectionn&amp;eacute;\r\naccount.confirmation.password.updated       =         Votre mot de passe a \u00e9t\u00e9 mis &amp;#224; jour.\r\nsearch.empty.message    = Nous n\\u2019avons pas trouv\u00e9 de r\u00e9sultats pour {0}\r\n<\/pre>\n<\/blockquote>\n<p>Furthermore, you don&#8217;t want to give a <code>.properties<\/code> file to a translator.  To a non-developer, they are quite unfriendly and, in my experience, <strong>translators will get confused and uncomfortable using them.<\/strong>  In this article, you&#8217;ll see how you can quickly fix these issues with <strong><a href=\"https:\/\/github.com\/zoltan-dulac\/z4n\"><code>z4n<\/code><\/a> a set of shell scripts I created to manage <code>.properties<\/code> files<\/strong> and includes tools for developers to <strong>extract translation data from Excel spreadsheets.<\/strong> Read on, and I&#8217;ll show you how to keep <code>.properites<\/code> files sane for all your web projects.<\/p>\n<p><a href=\"https:\/\/github.com\/zoltan-dulac\/z4n\" class=\"exampleLink\">Download z4n to manage your .properties files from GitHub<\/a><\/p>\n<h2>How To Fix Badly Formatted\/Managed .properties Files<\/h2>\n<p>In a large development shop, these files may start off well organized, but over time they become a rat&#8217;s nest of awful (as shown above).  The example above shows how some developers like to use <a href=\"https:\/\/en.wikipedia.org\/wiki\/Numeric_character_reference\">numeric entities<\/a>, while some other use <a href=\"https:\/\/en.wikipedia.org\/wiki\/List_of_XML_and_HTML_character_entity_references\">named entities<\/a> and still others use <a href=\"https:\/\/mathiasbynens.be\/notes\/javascript-escapes#unicode\">&#8216;\\u&#8217;-escaped Unicode characters<\/a>.  Furthermore, it seems that some developer like to add spaces at random around the equals sign that separates the key and the value.<\/p>\n<p>This has happened so many times in my career, which is why <code>z4n<\/code> has <code>removeEntitiesInProp<\/code> to prettify <code>.properties<\/code> file by converting everything to UTF-8 (as God intended all modern web applications to use) and standardizing the spacing around the = symbol. In seconds, you .properties files will no longer make your eyes bleed and want to go through git blame to see who messed up everything.<\/p>\n<h2>How To Make Them More Translator Friendly<\/h1>\n<p><code>z4n<\/code>&#8216;s <code>xls2prop<\/code> command is my favourite part of this package, though.  With it, you can give your translation department a nice Excel file like this:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/www.useragentman.com\/blog\/wp-content\/uploads\/2015\/09\/before.png\" alt=\"before\"  class=\"aligncenter size-full wp-image-7096 wideImage\" \/><\/p>\n<p>They can fill it out like this:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/www.useragentman.com\/blog\/wp-content\/uploads\/2015\/09\/after.png\" alt=\"after\" class=\"aligncenter size-full wp-image-7095 wideImage\" \/><\/p>\n<p>Then you can run <code>xls2prop<\/code> and you can get nicely formatted results for languages like Russian &#8230; :<\/p>\n<blockquote class=\"code\">\n<pre>\r\nform.header.name = \u0418\u043c\u044f\r\nform.header.address = \u0410\u0434\u0440\u0435\u0441\r\nform.header.postalcode = \u041f\u043e\u0447\u0442\u043e\u0432\u044b\u0439 \u0438\u043d\u0434\u0435\u043a\u0441\r\nform.header.city = \u0413\u043e\u0440\u043e\u0434\r\nform.header.province = \u041e\u0431\u043b\u0430\u0441\u0442\u044c\r\nform.header.country = \u0421\u0442\u0440\u0430\u043d\u0430\r\nregistration.intro.copy = \u041f\u043e\u0436\u0430\u043b\u0443\u0439\u0441\u0442\u0430, \u0437\u0430\u043f\u043e\u043b\u043d\u0438\u0442\u0435 \u0444\u043e\u0440\u043c\u0443 \u043d\u0438\u0436\u0435.\r\n<\/pre>\n<\/blockquote>\n<p>&#8230; and even Japanese:<\/p>\n<blockquote class=\"code\">\n<pre>\r\nform.header.name = \u540d\u524d\r\nform.header.address = \u4f4f\u6240\r\nform.header.postalcode = \u90f5\u4fbf\u756a\u53f7\r\nform.header.city = \u90fd\u5e02\r\nform.header.province = \u770c\r\nform.header.country = \u56fd\r\nregistration.intro.copy = \u4e0b\u8a18\u306e\u30d5\u30a9\u30fc\u30e0\u306b\u5fc5\u8981\u4e8b\u9805\u3092\u8a18\u5165\u3057\u3066\u304f\u3060\u3055\u3044\r\n<\/pre>\n<\/blockquote>\n<h2>Notes and Caveats<\/h2>\n<ul>\n<li>The z4n tools are shell scripts have been tested under OSX and Windows using <a href=\"http:\/\/cygwin.com\">Cygwin<\/a>.  I have not tested them under Linux yet (they should work, though).<\/li>\n<li>These tools use <a href=\"https:\/\/www.libreoffice.org\/\">LibreOffice<\/a> to convert a Microsoft Excel spreadsheet to a Unicode tab delimited format that the scripts can parse.  Note that a translator (or anyone who is trying to fill out the language spreadsheet) can use either Micrsoft Excel <em>or<\/em> Libre Office to do so.<\/li>\n<li><a href=\"http:\/\/billposer.org\/Software\/uni2ascii.html\">uni2ascii<\/a> by <a href=\"http:\/\/billposer.org\/\">Bill Poser<\/a>.  Since there was some issues compiling uni2ascii for Windows, I have included some Windows binaries that should work in the projects <code>win<\/code> directory, with instructions on how I did it.<\/li>\n<\/ul>\n<p><a href=\"https:\/\/github.com\/zoltan-dulac\/z4n\" class=\"exampleLink\">Download z4n to manage your .properties files from GitHub<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p><img decoding=\"async\" src=\"https:\/\/www.useragentman.com\/blog\/wp-content\/uploads\/2015\/10\/teaser.jpg\" \/> Although <strong><code>.properties<\/code> files<\/strong> are used to give multi-language support in JSP pages, they are not just restricted to <strong>Java<\/strong> platform &mdash; libraries exist for<strong> JavaScript, Ruby, Perl, Flex<\/strong> and a whole slew of other languages). When used in multi-developer environments, they <strong>can get rather messy and they can be rather translator unfriendly.<\/strong>  In this article, you&#8217;ll see how you can quickly fix these issues with <strong>z4n, a set of shell scripts I created to manage <code>.properties<\/code> files<\/strong> and includes tools for developers to <strong>extract translation data from Excel spreadsheets<\/strong>.  Read on, and I&#8217;ll show you how to keep <code>.properites<\/code> files sane for all your web projects.<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[77,175,174,179],"tags":[178,189,190,188,88,89,177,176,187,180,186,183,181,182,184,185,227],"class_list":["post-7089","post","type-post","status-publish","format-standard","hentry","category-internationalization","category-localization","category-server-side-tech","category-utf8","tag-properties","tag-entities","tag-escaped-characters","tag-human-language","tag-i18n","tag-internationalization-2","tag-java","tag-l10n","tag-language","tag-localization-2","tag-multi-lingual","tag-translater","tag-translation","tag-translator","tag-unicode","tag-utf-8","tag-utf8"],"_links":{"self":[{"href":"http:\/\/www.useragentman.com\/blog\/wp-json\/wp\/v2\/posts\/7089","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/www.useragentman.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/www.useragentman.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/www.useragentman.com\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"http:\/\/www.useragentman.com\/blog\/wp-json\/wp\/v2\/comments?post=7089"}],"version-history":[{"count":32,"href":"http:\/\/www.useragentman.com\/blog\/wp-json\/wp\/v2\/posts\/7089\/revisions"}],"predecessor-version":[{"id":7132,"href":"http:\/\/www.useragentman.com\/blog\/wp-json\/wp\/v2\/posts\/7089\/revisions\/7132"}],"wp:attachment":[{"href":"http:\/\/www.useragentman.com\/blog\/wp-json\/wp\/v2\/media?parent=7089"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.useragentman.com\/blog\/wp-json\/wp\/v2\/categories?post=7089"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.useragentman.com\/blog\/wp-json\/wp\/v2\/tags?post=7089"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}