Simon Brown Posted May 3, 2010 Share Posted May 3, 2010 I have written a class which I plan to use to translate my plugins when released (and has already been used for ExtendBorder) and am publishing it here to be freely used by other plugin authors if they wish. Language packs should be placed in Effects, include the language code in its name and have the extension .fxlang. More than one language pack can be used to help cover a single language. See the basic language pack attached for an example. When creating a language pack, make sure the character encoding is set to UTF-8. The code (v1.1): Hidden Content: using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Globalization; using System.Collections; using System.IO; namespace YourPluginNamespace { public class PluginTrans { Hashtable transTable = null; String plgLang = null; public PluginTrans() { plgLang = CultureInfo.CurrentUICulture.Name.ToLower(); String langDir = Path.Combine(Environment.CurrentDirectory, "Effects"); if (!Directory.Exists(langDir)) return; transTable = new Hashtable(); DirectoryInfo langDirInfo = new DirectoryInfo(langDir); FileInfo[] langFiles = langDirInfo.GetFiles(); for (int i = 0; i < langFiles.Length; i++) { if (FileIsLanguage(langFiles[i], plgLang)) { using (StreamReader curLangReader = new StreamReader(langFiles[i].FullName)) { while (!curLangReader.EndOfStream) { String curLine = curLangReader.ReadLine(); KeyValuePair<String, String> curTrans = ReadTransLine(curLine); if (!String.IsNullOrEmpty(curTrans.Key)) { transTable[curTrans.Key] = curTrans.Value; } } } } } } private static bool FileIsLanguage(FileInfo input, String locale) { return (input.Name.ToLower().Contains(locale.ToLower()) && input.Extension.ToLower() == ".fxlang"); } public static KeyValuePair<String, String> ReadTransLine(String input) { int colonPos = input.IndexOf(":"); int eqSignPos = input.IndexOf("="); if (colonPos != -1 && eqSignPos != -1 && input.Length > eqSignPos + 2) { String termKey = input.Substring(0, eqSignPos).ToLower(); String termValue = input.Substring(eqSignPos + 1); return new KeyValuePair<String, String>(termKey, termValue); } return new KeyValuePair<String, String>(null, null); } /// <summary> /// Gets the translation for a term. /// </summary> /// <param name="keyTerm"> /// en-US version of the term. /// </param> /// <param name="defaultTerm"> /// Term to be used if no translation exists. /// </param> /// <returns></returns> public String GetTrans(String keyTerm, String defaultTerm) { String tableKey = String.Format("{0}:{1}", plgLang, keyTerm.ToLower()); if (transTable.ContainsKey(tableKey)) { return (String)transTable[tableKey]; } return defaultTerm; } /// <summary> /// Gets the translation of a term. /// </summary> /// <param name="keyTerm"> /// en-US version of the term. /// </param> /// <returns></returns> public String GetTrans(String keyTerm) { return GetTrans(keyTerm, keyTerm); } } } Language pack repository: http://github.com/simonbrown/PluginTrans/blob/master/de%20and%20fr%20default.fxlang If anyone wants to contribute, PM me your Github username. It might also be possible to suggest edits without being one, although i'm not sure. Default language pack (v1.2) defaultpack.zip Quote Link to comment Share on other sites More sharing options...
Rick Brewster Posted May 3, 2010 Share Posted May 3, 2010 if (plgLang == null) throw new ApplicationException("Call init plz. Kthx."); Or you could just call Init() for them, and make Init() a private method. Quote The Paint.NET Blog: https://blog.getpaint.net/ Donations are always appreciated! https://www.getpaint.net/donate.html Link to comment Share on other sites More sharing options...
MadJik Posted May 3, 2010 Share Posted May 3, 2010 I don't know how but it would be great to use text file per language, so everyone could create his own translation if it doesn't exist and this task won't belong only to the plugin maker. Quote My DeviantArt | My Pictorium | My Plugins | Donate via Paypal Link to comment Share on other sites More sharing options...
pyrochild Posted May 3, 2010 Share Posted May 3, 2010 Yeah, this would work much better with external files like Paint.NET already uses. Quote ambigram signature by Kemaru [i write plugins and stuff] If you like a post, upvote it! Link to comment Share on other sites More sharing options...
Simon Brown Posted May 3, 2010 Author Share Posted May 3, 2010 if (plgLang == null) throw new ApplicationException("Call init plz. Kthx."); Or you could just call Init() for them, and make Init() a private method. The first time a plugin requests a translation might be in a separate thread. Yeah, this would work much better with external files like Paint.NET already uses. Good idea. Quote Link to comment Share on other sites More sharing options...
Simon Brown Posted May 3, 2010 Author Share Posted May 3, 2010 Good idea. The only problem is that it will have to be in a folder other than Paint.NET User Files. As when an effect's constructor is called, that information isn't available, and that might be a plugin's only chance to call Init. I'm not sure whether it's best to store this in Paint.NET's Program Files folder, AppData, or somewhere else. Quote Link to comment Share on other sites More sharing options...
Frontcannon Posted May 3, 2010 Share Posted May 3, 2010 This is just getting better and better. Quote Night Vision Text Effect Tutorial Gallery reddit.com/r/futurebeats | My Mixcloud Link to comment Share on other sites More sharing options...
pyrochild Posted May 3, 2010 Share Posted May 3, 2010 The only problem is that it will have to be in a folder other than Paint.NET User Files. As when an effect's constructor is called, that information isn't available, and that might be a plugin's only chance to call Init. I'm not sure whether it's best to store this in Paint.NET's Program Files folder, AppData, or somewhere else. You're over-thinking it. There's nothing wrong with Paint.NET\Effects\, and rather than having a static class that has to be Initted, just make an instance class that has to be created in the Effect's ctor. Quote ambigram signature by Kemaru [i write plugins and stuff] If you like a post, upvote it! Link to comment Share on other sites More sharing options...
Simon Brown Posted May 3, 2010 Author Share Posted May 3, 2010 You're over-thinking it. There's nothing wrong with Paint.NET\Effects\, and rather than having a static class that has to be Initted, just make an instance class that has to be created in the Effect's ctor. Thanks, i'll do that. Update posted. Quote Link to comment Share on other sites More sharing options...
Rick Brewster Posted May 3, 2010 Share Posted May 3, 2010 The first time a plugin requests a translation might be in a separate thread. Then either use a mutex, or use a local variable to create the dictionary and then assign it to the static field as the very last step. Quote The Paint.NET Blog: https://blog.getpaint.net/ Donations are always appreciated! https://www.getpaint.net/donate.html Link to comment Share on other sites More sharing options...
Simon Brown Posted May 3, 2010 Author Share Posted May 3, 2010 Then either use a mutex, or use a local variable to create the dictionary and then assign it to the static field as the very last step. It was because of: For now I'd just use CultureInfo.CurrentUICulture. This isn't guaranteed to be correct since it has to be set per-thread, so pretty much only the UI thread will have the "correct" value. But, Effects are (currently) instantiated on the UI thread for this so you can at least access it in your constructor. And at that time it was a static class, which it now isn't. Although on second thought, obviously plugins will only need the translations in the UI thread. Quote Link to comment Share on other sites More sharing options...
pyrochild Posted May 3, 2010 Share Posted May 3, 2010 Ill def be using this at some point. Ive already had offers to translate my plugins into german and russian. Quote ambigram signature by Kemaru [i write plugins and stuff] If you like a post, upvote it! Link to comment Share on other sites More sharing options...
MadJik Posted May 3, 2010 Share Posted May 3, 2010 Could you provide the source of ExtendBorder to see how to implement this? Or Some part of the code in the plugin side? Quote My DeviantArt | My Pictorium | My Plugins | Donate via Paypal Link to comment Share on other sites More sharing options...
Simon Brown Posted May 3, 2010 Author Share Posted May 3, 2010 I'll post the relevant parts. (SNIP) PluginTrans pluginTrans; public ExtendBorderEffect() : base("Extend border", null, SubmenuNames.Distort, EffectFlags.Configurable) { pluginTrans = new PluginTrans(); } (SNIP) protected override ControlInfo OnCreateConfigUI(PropertyCollection props) { ControlInfo uiBuilder = base.OnCreateConfigUI(props); uiBuilder.SetPropertyControlType("Left", PropertyControlType.Slider); uiBuilder.SetPropertyControlType("Top", PropertyControlType.Slider); uiBuilder.SetPropertyControlType("Right", PropertyControlType.Slider); uiBuilder.SetPropertyControlType("Bottom", PropertyControlType.Slider); uiBuilder.SetPropertyControlValue("Left", ControlInfoPropertyNames.DisplayName, pluginTrans.GetTrans("left", "Left")); uiBuilder.SetPropertyControlValue("Top", ControlInfoPropertyNames.DisplayName, pluginTrans.GetTrans("top", "Top")); uiBuilder.SetPropertyControlValue("Right", ControlInfoPropertyNames.DisplayName, pluginTrans.GetTrans("right", "Right")); uiBuilder.SetPropertyControlValue("Bottom", ControlInfoPropertyNames.DisplayName, pluginTrans.GetTrans("bottom", "Bottom")); return uiBuilder; } (SNIP) Quote Link to comment Share on other sites More sharing options...
BoltBait Posted May 3, 2010 Share Posted May 3, 2010 So, you still have to send your strings into the translator in English? MadJik might like it if he could program in French... [/ignore me, I'm a trouble maker] Quote Download: BoltBait's Plugin Pack | CodeLab | and a Free Computer Dominos Game Link to comment Share on other sites More sharing options...
Frontcannon Posted May 3, 2010 Share Posted May 3, 2010 Just revised the German parts of the pack. It would be nice if the translator would know what entry he'd be dealing with, context is always important when translating words. 'forever' has alone 3 possible expressions in German.. defaultpack.zip Quote Night Vision Text Effect Tutorial Gallery reddit.com/r/futurebeats | My Mixcloud Link to comment Share on other sites More sharing options...
Simon Brown Posted May 3, 2010 Author Share Posted May 3, 2010 Language pack updated. Thanks, VatherLokus and Frontcannon. Quote Link to comment Share on other sites More sharing options...
Simon Brown Posted May 3, 2010 Author Share Posted May 3, 2010 To translators: would you be okay using GitHub to edit the translation file? While it's intended to be used with a special program it's possible to edit the files online. Quote Link to comment Share on other sites More sharing options...
Frontcannon Posted May 3, 2010 Share Posted May 3, 2010 Looks alright, just signed up... Quote Night Vision Text Effect Tutorial Gallery reddit.com/r/futurebeats | My Mixcloud Link to comment Share on other sites More sharing options...
Simon Brown Posted May 3, 2010 Author Share Posted May 3, 2010 Are you okay with it being licensed under CC-BY (the language pack)? Quote Link to comment Share on other sites More sharing options...
Frontcannon Posted May 3, 2010 Share Posted May 3, 2010 OK with me, but how will we manage the mention of the authors? Should we keep that .txt file? Quote Night Vision Text Effect Tutorial Gallery reddit.com/r/futurebeats | My Mixcloud Link to comment Share on other sites More sharing options...
Simon Brown Posted May 3, 2010 Author Share Posted May 3, 2010 I'll keep a LICENSE file with the license and the authors. Quote Link to comment Share on other sites More sharing options...
Frontcannon Posted May 3, 2010 Share Posted May 3, 2010 So who will decide what we translate? I'd just go with the pinned PlugIn-Packs.. though the authors will have to submit some kind of template we can use in our language pack, don't they? Quote Night Vision Text Effect Tutorial Gallery reddit.com/r/futurebeats | My Mixcloud Link to comment Share on other sites More sharing options...
Simon Brown Posted May 3, 2010 Author Share Posted May 3, 2010 I've created the repository, and added you as a collaborator (assuming your username there is the same as it is here). See the first post for the URI. though the authors will have to submit some kind of template we can use in our language pack, don't they? My initial hope was that the key could just be the phrase in US-English (which doesn't have the be the default label), although that might not be practical. I guess that seems like the best option if there's anything that isn't obvious (e.g. more than color instead of colour). Quote Link to comment Share on other sites More sharing options...
Frontcannon Posted May 3, 2010 Share Posted May 3, 2010 Still getting the hang of GitHub.. what's 'forking'? And how do you add comments to our repository? :red: Quote Night Vision Text Effect Tutorial Gallery reddit.com/r/futurebeats | My Mixcloud Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.