diff --git a/README.md b/README.md
index 9671e11..03c249f 100644
--- a/README.md
+++ b/README.md
@@ -445,6 +445,23 @@ Nuggets translations can be modified at runtime as follows:
}
```
+#### PO customization
+
+i18n allows you to change the PO file name to use and use PO files from other sources (when working with multiple projects for example).
+To enable this feature, you can set :
+
+
+```xml
+
+ ...
+
+
+ ...
+
+```
+
+Note : i18n.LocaleOtherFiles paths are relative to the directory of the file {i18n.LocaleFilename}.po (messages.po by default).
+
### URL Localization
In keeping with emerging standards for internationalized web applications, i18n provides support for
diff --git a/src/i18n.Domain/Concrete/POTranslationRepository.cs b/src/i18n.Domain/Concrete/POTranslationRepository.cs
index 609cf0a..85bf6d8 100644
--- a/src/i18n.Domain/Concrete/POTranslationRepository.cs
+++ b/src/i18n.Domain/Concrete/POTranslationRepository.cs
@@ -142,7 +142,7 @@ public CacheDependency GetCacheDependencyForAllLanguages()
/// The translation you wish to save. Must have Language shortag filled out.
public void SaveTranslation(Translation translation)
{
- var templateFilePath = GetAbsoluteLocaleDir() + "/messages.pot";
+ var templateFilePath = GetAbsoluteLocaleDir() + "/" + _settings.LocaleFilename + ".pot";
var POTDate = DateTime.Now;
if (File.Exists(templateFilePath)) {
POTDate = File.GetLastWriteTime(templateFilePath); }
@@ -258,7 +258,7 @@ public void SaveTranslation(Translation translation)
/// A list of template items to save. The list should be all template items for the entire project.
public void SaveTemplate(IDictionary items)
{
- string filePath = GetAbsoluteLocaleDir() + "/messages.pot";
+ string filePath = GetAbsoluteLocaleDir() + "/" + _settings.LocaleFilename + ".pot";
string backupPath = filePath + ".backup";
if (File.Exists(filePath)) //we backup one version. more advanced backup solutions could be added here.
@@ -350,9 +350,11 @@ private string GetAbsoluteLocaleDir()
return _settings.LocaleDirectory;
}
- private string GetPathForLanguage(string langtag)
+ private string GetPathForLanguage(string langtag, string filename = null)
{
- return Path.Combine(GetAbsoluteLocaleDir(), langtag, "messages.po");
+ if (!filename.IsSet())
+ filename = _settings.LocaleFilename;
+ return Path.Combine(GetAbsoluteLocaleDir(), langtag, filename + ".po");
}
///
@@ -370,83 +372,97 @@ private Translation ParseTranslationFile(string langtag)
translation.LanguageInformation = language;
var items = new ConcurrentDictionary();
- string path = GetPathForLanguage(langtag);
-
- if (File.Exists(path)) {
- DebugHelpers.WriteLine("Reading file: {0}", path);
-
- using (var fs = File.OpenText(path))
- {
- // http://www.gnu.org/s/hello/manual/gettext/PO-Files.html
-
- string line;
- bool itemStarted = false;
- while ((line = fs.ReadLine()) != null)
- {
- var extractedComments = new List();
- var translatorComments = new List();
- var flags = new List();
- var references = new List();
-
- //read all comments, flags and other descriptive items for this string
- //if we have #~ its a historical/log entry but it is the messageID/message so we skip this do/while
- if (line.StartsWith("#") && !line.StartsWith("#~"))
- {
- do
- {
- itemStarted = true;
- switch (line[1])
- {
- case '.': //Extracted comments
- extractedComments.Add(line.Substring(2).Trim());
- break;
- case ':': //references
- references.Add(ReferenceContext.Parse(line.Substring(2).Trim()));
- break;
- case ',': //flags
- flags.Add(line.Substring(2).Trim());
- break;
- case '|': //msgid previous-untranslated-string - NOT used by us
- break;
- default: //translator comments
- translatorComments.Add(line.Substring(1).Trim());
- break;
- }
-
- } while ((line = fs.ReadLine()) != null && line.StartsWith("#"));
- }
-
- if (line != null && (itemStarted || line.StartsWith("#~")))
- {
- TranslationItem item = ParseBody(fs, line, extractedComments);
- if (item != null) {
- //
- item.TranslatorComments = translatorComments;
- item.ExtractedComments = extractedComments;
- item.Flags = flags;
- item.References = references;
- //
- items.AddOrUpdate(
- item.MsgKey,
- // Add routine.
- k => {
- return item;
- },
- // Update routine.
- (k, v) => {
- v.References = v.References.Append(item.References);
- var referencesAsComments = item.References.Select(r => r.ToComment()).ToList();
- v.ExtractedComments = v.ExtractedComments.Append(referencesAsComments);
- v.TranslatorComments = v.TranslatorComments.Append(referencesAsComments);
- v.Flags = v.Flags.Append(referencesAsComments);
- return v;
- });
+ List paths = new List();
+
+ paths.Add(GetPathForLanguage(langtag));
+
+ foreach (var file in _settings.LocaleOtherFiles)
+ {
+ paths.Add(GetPathForLanguage(langtag, file));
+ }
+
+ foreach (var path in paths)
+ {
+ if (File.Exists(path))
+ {
+ DebugHelpers.WriteLine("Reading file: {0}", path);
+
+ using (var fs = File.OpenText(path))
+ {
+ // http://www.gnu.org/s/hello/manual/gettext/PO-Files.html
+
+ string line;
+ bool itemStarted = false;
+ while ((line = fs.ReadLine()) != null)
+ {
+ var extractedComments = new List();
+ var translatorComments = new List();
+ var flags = new List();
+ var references = new List();
+
+ //read all comments, flags and other descriptive items for this string
+ //if we have #~ its a historical/log entry but it is the messageID/message so we skip this do/while
+ if (line.StartsWith("#") && !line.StartsWith("#~"))
+ {
+ do
+ {
+ itemStarted = true;
+ switch (line[1])
+ {
+ case '.': //Extracted comments
+ extractedComments.Add(line.Substring(2).Trim());
+ break;
+ case ':': //references
+ references.Add(ReferenceContext.Parse(line.Substring(2).Trim()));
+ break;
+ case ',': //flags
+ flags.Add(line.Substring(2).Trim());
+ break;
+ case '|': //msgid previous-untranslated-string - NOT used by us
+ break;
+ default: //translator comments
+ translatorComments.Add(line.Substring(1).Trim());
+ break;
+ }
+
+ } while ((line = fs.ReadLine()) != null && line.StartsWith("#"));
+ }
+
+ if (line != null && (itemStarted || line.StartsWith("#~")))
+ {
+ TranslationItem item = ParseBody(fs, line, extractedComments);
+ if (item != null)
+ {
+ //
+ item.TranslatorComments = translatorComments;
+ item.ExtractedComments = extractedComments;
+ item.Flags = flags;
+ item.References = references;
+ //
+ items.AddOrUpdate(
+ item.MsgKey,
+ // Add routine.
+ k => {
+ return item;
+ },
+ // Update routine.
+ (k, v) =>
+ {
+ v.References = v.References.Append(item.References);
+ var referencesAsComments =
+ item.References.Select(r => r.ToComment()).ToList();
+ v.ExtractedComments = v.ExtractedComments.Append(referencesAsComments);
+ v.TranslatorComments = v.TranslatorComments.Append(referencesAsComments);
+ v.Flags = v.Flags.Append(referencesAsComments);
+ return v;
+ });
+ }
}
- }
- itemStarted = false;
- }
- }
+ itemStarted = false;
+ }
+ }
+ }
}
translation.Items = items;
return translation;
diff --git a/src/i18n.Domain/Concrete/i18nSettings.cs b/src/i18n.Domain/Concrete/i18nSettings.cs
index d4014e2..6bb6297 100644
--- a/src/i18n.Domain/Concrete/i18nSettings.cs
+++ b/src/i18n.Domain/Concrete/i18nSettings.cs
@@ -72,6 +72,51 @@ public virtual string LocaleDirectory
#endregion
+ #region Locale filename
+
+ private const string _localeFilenameDefault = "messages";
+ public virtual string LocaleFilename
+ {
+ get
+ {
+ string prefixedString = GetPrefixedString("LocaleFilename");
+ string setting = _settingService.GetSetting(prefixedString);
+ if (setting.IsSet())
+ {
+ return setting;
+ }
+
+ return _localeFilenameDefault;
+ }
+ set
+ {
+ string prefixedString = GetPrefixedString("LocaleFilename");
+ _settingService.SetSetting(prefixedString, value);
+ }
+ }
+
+ private const string _localeOtherFilesDefault = "";
+ public virtual IEnumerable LocaleOtherFiles
+ {
+ get
+ {
+ string prefixedString = GetPrefixedString("LocaleOtherFiles");
+ string setting = _settingService.GetSetting(prefixedString);
+ if (!setting.IsSet())
+ {
+ setting = _localeOtherFilesDefault;
+ }
+
+ return setting.Split(';');
+ }
+ set
+ {
+ string prefixedString = GetPrefixedString("LocaleOtherFiles");
+ _settingService.SetSetting(prefixedString, string.Join(";", value));
+ }
+ }
+
+ #endregion
#region White list