Skip to content

Latest commit

 

History

History
305 lines (222 loc) · 8.44 KB

README.md

File metadata and controls

305 lines (222 loc) · 8.44 KB

MN.L10n Build status Gitter chat

Translation-thingy for all our products

You must implement your IL10nLanguageProvider and a custom IFileResolver (for javascript) yourself. :) (Basically just string GetLanguage() and bool FileExists(string file))

There's also a custom mvc webview MN.L10n.Mvc.L10nWebView.

Example usage (C#)

using MN.L10n.NullProviders;
using MN.L10n.FileProviders;
using static MN.L10n.L10n;

void Main()
{
	var l10n = MN.L10n.L10n.CreateInstance(
		new NullLanguageProvider("en-GB"), 
		new FileDataProvider(@"C:\temp\phrase")
	);

	Console.WriteLine(
		_s("Det finns $__count$ meddelanden", 
			new { __count = 0 }
		)
	); // There are no messages
	
	Console.WriteLine(
		_s("Det finns $__count$ meddelanden", 
			new { __count = 1 }
		)
	); // There is one message
	
	Console.WriteLine(
		_s("Det finns $__count$ meddelanden", 
			new { __count = 2 }
		)
	); // There are 2 messages
	
	Console.WriteLine(
		_m("[Hejsan $name$](http://www.multinet.se)", 
			new { name = "Anders" }
		)
	); // <p><a href="http://www.multinet.se">Hejsan Anders</a></p>
}

These are the methods available:

  • _s(string phrase, object args = null): Normal string for translation
  • _sr(string phrase, object args = null): Same as above, but for output in MVC/Razor (Returns IHtmlContent)
  • _m(string phrase, object args = null): Markdown-string for translation
  • _mr(string phrase, object args = null): Same as above, but for output in MVC/Razor (Returns IHtmlContent)

Example usage (Javascript)

First you need to link our javascript into the pages where you want to enable global usage of _s and _m.

<%
Response.Write("<script type=\"text/javascript\">" + 
  MN.L10n.Properties.Resources.L10n + 
"</script>");
%>
DealDetails.ShowNotification(
  _s('Sparade en ny notering på $companyName$', 
    { companyName: DealDetails.DealInfo.CompanyName }
  )
);

Global.asax.cs

protected void Application_Start(object sender, EventArgs e)
{
  ...
  MN.L10n.L10n.CreateInstance(new IL10nLanguageProvider(), new FileDataProvider(@"C:\temp\phrase"));
  ...
}

L10n and you, a guide for translations and localization

This part of the documentation will provide information for you to know:

How to install MN.L10n

To be able to use MN.L10n, you have to install the NuGet-package from our Artifactory into all projects where you want to be able to use it for translation.

The best way to use it, is to actually add it as using static MN.L10n.L10n; in your usings, because then you can use _s and _m directly, without having to prefix it with L10n._s.

And to be able to get the files for translation, you also need to install MN.L10n.BuildTasks, into one or more projects, depending on how many projects you want different "projects" for in i.e. GlotPress.

And then, to actually be able to use it, you have to create an instance of it.

MN.L10n.L10n.CreateInstance(
  new NullLanguageProvider("1"), // 1 in this case is the source language
  new FileDataProvider(@"C:\temp\phrase") // This is the path where you load the language from
);

There are different providers for different things, and most projects have their own LanguageProvider.

These are the methods available for translation:

  • _s(string phrase, object args = null): Normal string for translation
  • _sr(string phrase, object args = null): Same as above, but for output in MVC/Razor (Returns IHtmlContent)
  • _m(string phrase, object args = null): Markdown-string for translation
  • _mr(string phrase, object args = null): Same as above, but for output in MVC/Razor (Returns IHtmlContent)

How to get MN.L10n.BuildTasks to work

First of all, you need to install the NuGet-package MN.L10n.BuildTask in at least one project.

Currently, it will only run while the solution is being compiled in Release-config, so that we don't slow down local build times too much.

When the solution is run in Release-mode, L10n will look for either a .l10nconfig or the .sln-file, as the root for where it should look for phrases.


How to properly write phrases to be translated and pluralized

So, you want to use L10n the way you're supposed to? Awesome!

First of all, you have to decide what language is the Source Language. So, no mixing languages.

Pluralization

First, we'll go over what you shouldn't do, because I've seen this a lot.

if(numberVariable == 1) {
 _s("$__count$ thing", new { __count = numberVariable });
} else {
 _s("$__count$ things", new { __count = numberVariable });
}

Because this will register as two separate phrases that will need pluralization in GlotPress.

Instead, do it like this, because it will only register once by L10n, but still be pluralizable in GlotPress.

_s("$__count$ things", new { __count = numberVariable });

If you didn't notice from the examples, the magic property is called $__count$, please stop using your own names for variables that need pluralization, it won't work..


Line breaks

You handle line breaks by using any type of string, that supports new lines in them.

Javascript/TypeScript

_s(`This
is
SPARTA`);

C#

_s(@"This
is
SPARTA");

Don't ever use string concatenation, I do not want to see anything like this

_s("This" + Environment.NewLine + "is" + Environment.NewLine + "SPARTA");

Parameters/Variables

I don't remember right now that I have seen anyone use this the wrong way, but better safe than sorry.

Don't use string literals (strings with variables in it), it might work, but it's not intentional in that case.

Javascript/TypeScript

_s(`This ${isWord} not allowed, it is not intentionally supported, if it even works`);

C#

_s($"This {isWord} not allowed, it is not intentionally supported, if it even works");

Instead, if you want to use variables, the correct way for L10n, use it like this (bad example, but still)

_s(
 "This $isWord$ not allowed, it is not intentionally supported, if it even works",
 new { isWord = "is" }
);

Reserved variables

  • $__count$ / __count, used for pluralization.

Dynamic phrases

Normally, L10n does not allow dynamic phrases (you'll get those warnings from the MN.L10n.Analyzer, when you have it installed).

So, I won't be going into this here. L10n is not made for dynamic phrases. 😄


What is the .l10nconfig-thing

Example config

{
 /*
  * IncludePatterns is an array that
  * will make sure that you won't miss
  * any packages in i.e. node_modules
  */
 "IncludePatterns": [
  "\\@multinet\\",
  "/@multinet/"
  ],

 /*
  * ExcludePatterns is an array that
  * will ignore some paths/folders,
  * so that you won't get double instances
  * phrases from compiled versions of the code
  */
 "ExcludePatterns": [
  "\\compiled\\"
  ],

 /* This will make the log, really verbose */
 "ShowDetailedLog": false,

 /* Well, it should be very obvious what this one does */
 "PreventBuildTask": false,

 /*
  * Setting this to true, will make the BuildTask
  * download the phrases from the sources in languages.json
  */
 "DownloadTranslationFromSourcesOnBuild": true,

 /*
  * An array of what directories L10n should
  * copy all it's compiled files to
  */
 "CopyFilesTo": [
  "sample-folder",
  "sample-folder2"
 ],

 /* This is the language the app is written in */
 "SourceLanguage": "1"
}

How do I languages.json

Example config

[
 {
  /* This should map to the language identifier in your application */
  "LanguageId": "1",

  /* Sources contains an array of URLs from where we should download translations on build */
  "Sources": [
  ]
 }
]

Things we use in the code to make the magic happen