Website localization is for the most part a complicated process which can drive us loco. So Lingumania was designed specifically with simplicity in mind. Get your website localized with minimal effort!
-
1
Start by providing translation data for your webpage
copyvar linguJSON = { "languages": [ { "lang_name": "English", "lang_code": "en", "url_pattern": "?" }, { "lang_name": "Español", "lang_code": "es", "url_pattern": "?" } ], "translated_segments": [ { "source": "Ready to go global?", "target": "¿Está listo para el mundo?" }, { "source": "get found by search engines and visitors in other languages", "target": "sea encontrado por los motores de búsqueda en otros idiomas" }, { "source": "Powered by <strong>Lingumania</strong>", "target": "Potenciado por <strong>Lingumania</strong>" } ] };
or put it in a separate file that your system can generatecopy<script src="https://path.com/to/the/JavaScript/page-translations.js"></script>
-
2
Include lingumania.js or lingumania.min.js
copy<script src="https://path.com/to/the/JavaScript/lingumania.min.js"></script>
-
3
Repeat steps 1 and 2 on any page that you want translated
Here's what the above code produces:
Page output
View HTML
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta charset="utf-8" />
</head>
<body>
<h1>Ready to go global?</h1>
<h2>get found by search engines and visitors in other languages</h2>
<a href="/Demos/QuickDemo.html">Powered by <strong>Lingumania</strong></a>
<script type="text/javascript">
var linguJSON = {
"languages": [
{
"lang_name": "English",
"lang_code": "en",
"url_pattern": "?"
},
{
"lang_name": "Español",
"lang_code": "es",
"url_pattern": "?"
}
],
"translated_segments": [
{
"source": "Ready to go global?",
"target": "¿Está listo para el mundo?"
},
{
"source": "get found by search engines and visitors in other languages",
"target": "sea encontrado por los motores de búsqueda en otros idiomas",
},
{
"source": "Powered by <strong>Lingumania</strong>",
"target": "Potenciado por <strong>Lingumania</strong>"
}
]
};
</script>
<script src="js/lingumania.min.js"></script>
</body>
</html>
Structure of Translation Data
Translation data for your webpage is a JSON object containing everything that lingumania.js needs to render your SEO-friendly translated page.
languages
Languages section contains the basic setup required to output the language switcher menu. It is a JSON array that starts with your original language, followed by all the translation languages that your page supports.
Property | Description |
---|---|
lang_name | Name of the language as it will appear in the language switcher menu (usually written in native script) |
lang_code | The 2 letter code that you'll use to identify this language in the url. The code can appear in the url query string (ie. ?lang=fr), subdirectory (ie. yourdomain.com/fr/) or subdomain (ie. fr.yourdomain.com). |
url_pattern |
The url pattern that you're using for translated pages. Can be one of the following:
|
Your source language should be the first language to appear in the languages array, followed by all your translation languages.
translated_segments
Translated_segments section contains source / target language translation pairs for all the text blocks (segments) that appears on your webpage. This includes free standing text (such as blocks within div
and span
tags), link hrefs, button labels, dropdown options, image alt attributes, and meta tags.
Property | Description |
---|---|
source | Each text block (segment) in its original language |
target | Translation of the source |
Alternatively, you may choose to output translations in all your supported languages in one JSON. In that case each object in your translated_segments array will contain the source followed by all translations in different languages that you support (ie. source, target_fr, target_es, etc.)
Property | Description |
---|---|
source | Each text block (segment) in its original language |
target_{language code} | Translation of the source in your first supported language |
target_{language code} | Translation of the source in your second supported language |
target_{language code} | etc. |
Links can be "translated" too
Part of the localization idea is that you might want to serve completely different content for different locales. So occasionally you might want to rewrite links on your translated pages completely, so that in one language they might point to a completely different url than in the other.
To translate links, put the original absolute url (starting with http) in source
and then provide another absolute url in target
. Lingumania.js will then rewrite any occurrences of those links on your page.
Supported HTML tags in source/target
The following HTML tags that can be included in source and target strings:
translated_image_segments (optional)
If you have images containing text for which you have translated version you can include their list in the optional translated_image_segments section.
Property | Description |
---|---|
img_source | Full url to the original image file. For ex. "http://yourdomain.com/path/to/original-language-image.png" |
img_target | Full url to the translated image file. For ex. "http://yourdomain.com/path/to/translated-image.png" |
Similarly to translated_segments, if you choose to output translations in all your supported languages in one JSON, you can append _{language_code}
for each translated image src.
Property | Description |
---|---|
img_source | Full url to the original image file. For ex. "http://yourdomain.com/path/to/original-language-image.png" |
img_target_{language code} | Full url to the translated image file in your first supported language. For ex. "http://yourdomain.com/path/to/translated-image.png" |
img_target_{language code} | Full url to the translated image file in your second supported language. For ex. "http://yourdomain.com/path/to/another/translated-image.png" |
img_target_{language code} | etc. |
translated_pages (optional)
If you don't have all pages on your site translated, then you can input the urls of translated pages in this section. The language switcher menu will only be displayed on pages for which you have translations. This section can be omitted if all pages on your site are translated.
Property | Description |
---|---|
slug |
Url of your translated page without the domain:
|
custom_lang_switcher_html (optional)
If you wish to style your own custom language switcher menu, you can provide its HTML template in custom_lang_switcher_html section. Omitting this section will output the default language switcher menu which appears as a dropdown in the upper right corner of your website.
Property | Description |
---|---|
custom_lang_switcher_html | HTML template of your custom language switcher menu. For more information check out Customizing Language Switcher Menu. |
custom_lang_switcher_container_id (optional)
If you're using a custom language switcher, then you also need to provide the id
of the HTML element on your page that will output your custom language switcher menu.
Property | Description |
---|---|
custom_lang_switcher_container_id | id of the HTML element on your page that will output your custom language switcher menu. |
Demo
Here we put everything together to produce a page localized into French and Spanish:
View demo-JSON-translation-data.js
var linguJSON = {
"languages": [
{
"lang_name": "English",
"lang_code": "en",
"url_pattern": "www.lingumania.com"
},
{
"lang_name": "Español",
"lang_code": "es",
"url_pattern": "es.lingumania.com"
},
{
"lang_name": "Français",
"lang_code": "fr",
"url_pattern": "fr.lingumania.com"
}
],
"custom_lang_switcher_html": "<div id=\"langswitcher\" class=\"notranslate\"><a id=\"currlanglink\" href=\"\">[[linguCurrLang]]</a> <a href=\"[[linguTargetLangHref1]]\" class=\"targetlang\">[[linguTargetLang1]]</a><a href=\"[[linguTargetLangHref2]]\" class=\"targetlang\">[[linguTargetLang2]]</a></div>",
"custom_lang_switcher_container_id": "langlinks",
"translated_segments": [
{
"source": "Are you doing a good job at attracting international guests?",
"target_fr": "Attirez-vous le plus de visiteurs internationaux possible?",
"target_es": "¿Consigue atraer huéspedes internacionales?"
},
{
"source": "Contact Us",
"target_fr": "Contact",
"target_es": "Contáctenos"
},
{
"source": "Even if your international guests speak English and they manage to find you online, they'll likely warm up to content in their own language. It may just be that final factor that helps them choose your property over a competitor's hotel that does not yet have a site in their own language.",
"target_fr": "Même si vos visiteurs internationaux parlent l'anglais et qu'ils réussissent à vous trouver en ligne, ils vont préférer un contenu dans leur langue. Il peut s'agir de l'élément qui les incite à choisir votre propriété plutôt que celle d'un concurrent qui n'a pas encore un site offert dans leur langue.",
"target_es": "Incluso si sus huéspedes internacionales hablan Inglés y logran encontrarlo en línea, posiblemente se sentirán más cómodos con contenido en su propio idioma. Podría ser el factor final que lo ayuden a elegir su propiedad por sobre la de un hotel competidor que todavía no tiene un sitio en su idioma."
},
{
"source": "Foreign language content also gives your hotel <strong>more prominence</strong>, meaning more mentions in foreign language social media, as well as more listings in hotel, B&B and inn web directories and aggregators.",
"target_fr": "Un contenu en langue étrangère donne aussi à votre hôtel une plus <strong>grande diffusion</strong>, soit plus de mentions dans les médias sociaux de langue étrangère, ainsi que plus d'inscriptions dans les répertoires d'hôtels et aggrégateurs en ligne.",
"target_es": "El contenido en idiomas extranjeros también le da a su hotel <strong>más importancia</strong>, lo que significa más menciones en los medios sociales en idiomas extranjeros, como también más listados en directorios Web y distribuidores de información de hoteles, B&B y postas."
},
{
"source": "Happy hotel guest",
"target_fr": "Client heureux",
"target_es": "Huésped de hotel feliz"
},
{
"source": "Home",
"target_fr": "Accueil",
"target_es": "Inicio"
},
{
"source": "Instead of relying just on Online travel agencies (OTAs) to drive your reservations, you've invested in content marketing and built a great website. But what happens when <em>international guests</em> try to find you online?",
"target_fr": "Au lieu de vous fier seulement aux agences de voyage en ligne pour obtenir des réservations, vous avez investi dans le marketing de contenu et créez un superbe site Web. Mais que se passe-t-il lorsque les <em>visiteurs internationaux</em> essaient de vous trouver en ligne?",
"target_es": "En vez de confiar solamente en agencias de viajes en línea (OTA por su siglas en inglés) para dirigir sus reservas, usted invirtió en mercadeo de contenido y constriyó un excelente sitio Web. Pero ¿ que sucede cuando los <em>huéspedes internacionales</em> intentan buscarlos en línea?"
},
{
"source": "What about using free machine translation on your hotel website? Besides the fact that poorly translated content could actually hurt your brand, machine translation widgets don't provide any SEO (search engine optimization) benefits, since they only translate \"on-the-fly\", and search engines <em>can't index their output.</em>",
"target_fr": "Qu'en est-il de la traduction automatique gratuite? En plus du fait qu'un contenu mal traduit peut nuire à votre marque, les widgets de traduction automatique ne fournissent aucun avantage de référencement puisque la traduction est «instantanée» et que les moteurs de recherche <em>ne peuvent classer ces données.</em>",
"target_es": "¿Y que sucede con la traducción gratis por máquina del su sitio Web de su hotel? Además del hecho de que el contenido que está pobremente traducido le podría dañar a su marca, los widgets de traducción por máquina no proporcionan ningún beneficio de SEO (optimización para motor de búsqueda) ya que solo traducen \"sobre la marcha\" y los motores de búsqueda <em>no pueden indexar su producto.</em>"
},
{
"source": "Site or web page that you wish to translate (ie. http://www.example.com)",
"target_fr": "Site Web que vous désirez traduire (c.-à-d. http://exemple.com)",
"target_es": "Sitio o página Web que desea traducir (p. ej. http://www.example.com)"
},
{
"source": "Ready to go global?",
"target_fr": "Prêt pour l’international?",
"target_es": "¿Está listo para el mundo?"
},
{
"source": "They'll likely type a query in their own language and to respond to that query you'll need content in that language.",
"target_fr": "Ils entrent probablement une demande dans leur langue et pour pouvoir répondre à cette demande, vous avez besoin d'un contenu dans cette langue.",
"target_es": "Es probable que escriban una búsqueda en su idioma y para responder a esa búsqueda necesita contenido en dicho idioma."
},
{
"source": "Lingumania » Hotel Website Translation and Localization",
"target_fr": "Lingumania » Traduction et localisation de sites Web d'hôtels",
"target_es": "Lingumania » Traducción y localización de sitios Web de Hoteles"
},
{
"source": "all rights reserved.",
"target_fr": "tous droits réservés.",
"target_es": "todos los derechos reservados."
},
{
"source": "Hotel Website Translation", //example of title tag translation
"target_fr": "Traduction du site Web d'un hôtel",
"target_es": "Traducción de sitio Web de hoteles"
},
{
"source": "Try a demo!", //example of image alt tag translation
"target_fr": "Essayez une démo!",
"target_es": "¡Pruebe una demostración!"
},
{
"source": "mailto:[email protected]", //example of link rewriting: French and Spanish "Contact Us" link takes you to the homepage instead of pointing to the mailto link
"target_fr": "http://www.lingumania.com",
"target_es": "http://www.lingumania.com"
}
],
"translated_image_segments": [
{
"img_source": "http://www.lingumania.com/img/try-a-demo2.png",
"img_target_fr": "http://www.lingumania.com/img/try-a-demo-fr.png",
"img_target_es": "http://www.lingumania.com/Demos/assets/FFFFFF-0.8.png" //we don't have this image's Spanish translation, so we'll just link to a pixel image instead
}
],
"translated_pages": [
{
"slug": "/Demos/Demo.html" //we only have translation for this Demo page; other links on the page (ie. link to www.lingumania.com homepage will not be prefixed with fr.lingumania.com or es.lingumania.com)
}
]
};
View HTML
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="content-type" content="text/html;charset=UTF-8" />
<title>
Lingumania » Hotel Website Translation and Localization
</title>
<link rel="stylesheet" type="text/css" media="screen" href="assets/main.css" />
<link rel="stylesheet" type="text/css" media="screen" href="assets/style_lingu.css" />
</head>
<body>
<script src="js/demo-JSON-translation-data.js"></script> <!--all translation data for this page is in this file-->
<script src="js/lingumania.min.js"></script>
<form method="post" action="" id="form1">
<div id="wrapper">
<div id="pre_header">
<div id="pre_header_content">
<div id="featured">
</div>
</div>
</div>
<div id="header_wrapper">
<div id="top_header">
<div id="top_header_wrapper">
<div id="top_header_center">
<a id="ctl00_linguHeader_lingu_lnkHome" class="logo" href="http://www.lingumania.com"> </a>
</div>
<div id="top_header_right">
<div id="tabsContainer">
<ul class="navTabs" id="listMenuRoot"></ul>
</div>
</div>
</div>
</div>
</div>
<div id="content">
<div id="content_wrapper">
<div id="homeFeaturedContainer">
<div id="langlinks"><!--this is where we'll output out custom language switcher menu--></div>
<div style="clear:both; margin-bottom:3em;"><img src="http://www.lingumania.com/img/try-a-demo2.png" alt="Try a demo!" /></div>
<h1 class="clear">Are you doing a good job at attracting international guests?</h1>
<br /><br />
<h2>Instead of relying just on Online travel agencies (OTAs) to drive your reservations, you've invested in content marketing and built a great website. But what happens when <em>international guests</em> try to find you online?</h2>
<br /><br />
<div id="websiteTranslationLeft"><img src="assets/website-translation.png" /></div>
<div id="websiteTranslationRight">
<p>They'll likely type a query in their own language and to respond to that query you'll need content in that language. </p>
<br />
<p>What about using free machine translation on your hotel website? Besides the fact that poorly translated content could actually hurt your brand, machine translation widgets don't provide any SEO (search engine optimization) benefits, since they only translate "on-the-fly", and search engines <em>can't index their output.</em> </p>
</div>
<div id="happyHotelCustomerLeft">
<p>Foreign language content also gives your hotel <strong>more prominence</strong>, meaning more mentions in foreign language social media, as well as more listings in hotel, B&B and inn web directories and aggregators.</p>
<br />
<p>Even if your international guests speak English and they manage to find you online, they'll likely warm up to content in their own language. It may just be that final factor that helps them choose your property over a competitor's hotel that does not yet have a site in their own language.</p>
</div>
<div id="happyHotelCustomerRight"><img src="assets/happy-hotel-customer.png" alt="Happy hotel guest" /></div>
</div>
<div class="clear">
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script type="text/javascript">
$(document).ready(function () {
$('#txtURL').val($('#hdnTextBox').val());
});
</script>
<div class="go_global clear">
<h1>Ready to go global?</h1><br />
<div class="containerGlobal">
<div class='outerGlobal'>
<div class='innerGlobal'>
<input name="txtURL" type="text" id="txtURL" class="homepageTextBox greyItalic" onfocus="if (this.value==document.getElementById('hdnTextBox').value)this.value='';this.className='homepageTextBox';" onblur="if (this.value==''){this.value=document.getElementById('hdnTextBox').value;this.className='homepageTextBox greyItalic';}else{this.className='homepageTextBox';}" />
<a id="lbtGetStarted" class="getstarted_button">SIGN UP FREE</a>
</div>
<input name="hdnTextBox" type="text" value="Site or web page that you wish to translate (ie. http://www.example.com)" id="hdnTextBox" class="linguVal" />
</div>
</div>
<p></p>
</div>
<div> </div>
</div>
</div>
</div>
<div class="push"></div>
</div>
<div id="footer">
<div id="footer_inner">
<div id="footer_left">
<p>
<a href="http://www.lingumania.com">Home</a> | <a href="/demos/demo.html">Hotel Website Translation</a> | <a href="mailto:[email protected]">Contact Us</a>
</p>
<p>
</p>
<p>© 2023 lingumania - <span>all rights reserved.</span> </p>
</div>
</div>
</div>
</form>
</body>
</html>
Page output
Optimizing For Search Engines
Lingumania supports the query string url pattern by default (ie. by adding ?lang={language code}
to all your translated page urls). However, adding a subdomain or subdirectory structure for your translated pages will help search engines discover and index your translated pages. Having semantic urls is also more user friendly.
Using subdomains for your translated pages
Adding subdomains for your translated pages is easier than using subdirectories as it does not require making changes to your web server. Instead, all you need to do is go to your DNS registrar and create a new CNAME record for your subdomain and point it to your main website domain. You will need one subdomain for each language.
Let's say you have a domain called www.yourdomain.com and you want to create subdomains for French and Spanish. You'll need to create 2 new CNAME entries:
- fr.yourdomain.com CNAME www.yourdomain.com
- es.yourdomain.com CNAME www.yourdomain.com
Then you would put "fr.yourdomain.com" and "es.yourdomain.com" as url_pattern entries in your translation data JSON.
Using subdirectories for your translated pages
If you wish to have a directory on your site for each language (ie. yourdomain.com/fr/ for French), you need to set your web server to rewrite requests so that www.yourdomain.com/fr/ resolves to your homepage at www.yourdomain.com, and www.yourdomain.com/fr/subfolder/page resolves to www.yourdomain.com/subfolder/page.
This is an advanced setup method that varies from one web server to another. Here's an example of how this can be implemented in IIS:
<?xml version="1.0" encoding="utf-8" ?>
<rules>
<rule name="L10n Rewrite Root EN" stopProcessing="true">
<match url="^en$" />
<action type="Rewrite" url="/Default.aspx" />
</rule>
<rule name="L10n Rewrite EN" stopProcessing="false">
<match url="^en/(.*)$" />
<action type="Rewrite" url="{R:1}" />
</rule>
<rule name="L10n Rewrite Root FR" stopProcessing="true">
<match url="^fr$" />
<action type="Rewrite" url="/Default.aspx" />
</rule>
<rule name="L10n Rewrite FR" stopProcessing="false">
<match url="^fr/(.*)$" />
<action type="Rewrite" url="{R:1}" />
</rule>
<rule name="L10n Rewrite Root ES" stopProcessing="true">
<match url="^es$" />
<action type="Rewrite" url="/Default.aspx" />
</rule>
<rule name="L10n Rewrite ES" stopProcessing="false">
<match url="^es/(.*)$" />
<action type="Rewrite" url="{R:1}" />
</rule>
</rules>
If you're using WordPress, there are plugins such as Rewrite that can be used for this. Here's how you would set up rewrite rules for French and Spanish in that plugin.
Rule Pattern | Match |
---|---|
^fr$ | / |
^fr/(.*)$ | index.php?pagename=$matches[1] |
^es$ | / |
^es/(.*)$ | index.php?pagename=$matches[1] |
Finally you need to let lingumania.js know that you're using subdirectories by putting "/" as url_pattern entries in your translation data JSON.
Using query strings for your translated pages
Using query strings is the least preferred method but it's the fastest and easiest to set up. All you have to do is put "?" as url_pattern entries in your translation data JSON, and ?lang={langcode}
will be appended to your translated page urls.
FAQ
Begin typing your question. If it hasn't already been answered in the FAQ, feel free to get in touch via email
-
I still don't understand what a translation segment is? How do I generate list of segments from my webpage?
Translation segments are blocks of translatable text from your webpage. You can extract the segments manually or use an online tool such as Textise to do it for you. -
I don't speak another language. How can I actually translate the text?
Options include professional translators and/or machine translation. A good resource is Proz. -
What about support for pluralization or dynamic text that my web application generates?
Lingumania was conceived as a quick and simple way to localize most websites. While it should be sufficient for the vast majority of online content, it might not be the best choice for more complex localization scenarios. -
Can I use lingumania.js to translate my Angular JS app?
Lingumania works with rendered HTML so single page apps that render text dynamically are not supported. -
Will Lingumania work with any type of web server technology/programming language?
Yes with the exception of single page applications. To put it simply, if you can see the text that your page outputs when you click View Source in your browser then linguamania.js can see it too. -
Can it be used on commercial websites? Can I adapt lingumania.js code to fit my needs?
Lingumania is completely free for you to use on your commercial or non commercial website. You may modify the code only if you use it to translate your own website. Please see the license section for more details.
License and Terms of Use
Lingumania.js is licensed under the terms of https://creativecommons.org/licenses/by-nd/3.0/ license, which means it can be used freely on commercial or non commercial websites as long as you link back to www.lingumania.com. You may modify the code only if you use it to translate your own website. In all other cases, modifications or redistribution, whether standalone or as part of another javascript, are not permitted without prior consent of the copyright owners.