Translated File Action
This type of extension is called whenever the Beebox creates a translated file in the "out" directory of a project. This can be triggered manually from the Beebox UI or by an automatic operation. Some use cases:
- Copy the translated file to another location
- Rename translated files, e.g. if you need to suffix or prefix file names.
- Store translated files to a content management system
- Track for logging purposes or triggering other actions
Adding the extension is done in a few steps:
- Add a class that extendst BeeboxTranslatedFileAction.
- Code the Process() method. It is called with full details per created translated file.
- Compile and install your dll.
The code below is a sample implementation. All interface methods are verbosely commented and should be self-explanatory.
Renaming files
If you plan to rename translated files, make sure to always leave the original translated file unchanged. Instead, create a copy of the file and save it under a different name (and ideally in a different location to avoid conflicts).
Configuration options
The sample implementation below copies and renames translated files according to a user configurable pattern: Each file is copied to out\_copy\... and the file name is prefixed with the target language code.
We added code to permit Beebox administrator to customize the target folder (_copy) and the file renaming individually per project.
Sample class
The Beebox extension below copies and renames translated files.
using System; using System.Collections.Generic; using System.Linq; using System.Text; using Wordbee.Beebox.Extensibility; using System.IO; namespace Acme.PseudoTranslationSample { public class SampleTranslatedFileAction : BeeboxTranslatedFileAction { /// <summary> /// Gets the globally unique id of this extension. /// </summary> public override string ExtensionID { get { return "acme-tfa"; } } /// <summary> /// Gets if the extension is by default enabled. If false, then it must be enabled explicitly in each /// Beebox project from the Beebox Admin UI. /// </summary> public override bool EnableByDefault { get { return false; } } /// <summary> /// Gets a name. Displayed in the Beebox extension manager page. /// </summary> public override string Name { get { return "Copy translated files"; } } /// <summary> /// Gets a description. Displayed in the Beebox extension manager page. /// </summary> public override string Description { get { return "Copies all translated files to another location."; } } /// <summary> /// Gets version number. Displayed in the Beebox extension manager page. /// </summary> public override string Version { get { return "1.0"; } } /// <summary> /// Gets the author. Displayed in the Beebox extension manager page. /// </summary> public override string Author { get { return "Acme Ltd"; } } /// <summary> /// Gets optional help description (not html!) of the configuration parameter. /// By returning a non-null value, you explicitly tell the Beebox that this extension has a configurable parameter. /// </summary> public override string ParameterHelp { get { return "Specify the sub directory inside out folder to which files will be copied." + "Then the name transformation pattern. Separate with semi-colon.\n " + "The name pattern may contain:\n " + "{name} : The file name without extension.\n " + "{extension} : The file extension.\n " + "{tlocale} : The target language code.\n " + "{slocale} : The source language code.\n "; } } /// <summary> /// Gets the default value of the parameter. Default can be changed by user. /// </summary> public override string ParameterDefault { get { return @"_copy; {tlocale}-{name}{extension}"; } } /// <summary> /// Validates the user parameters. /// Return null if ok, otherwise return an error text. /// </summary> /// <param name="parameter">The parameter edited by a user.</param> /// <returns>Null: parameter is ok. Otherwise return an error message.</returns> public override string ValidateParameter(string parameter) { try { if (string.IsNullOrWhiteSpace(parameter)) return null; var arr = parameter.Split(';'); if (arr.Length != 2) return "Specify a subdirectory followed by semi-colon followed by name pattern."; // Here you need to check each array element in detail. if (string.IsNullOrWhiteSpace(arr[0])) return "The subdirectory name is missing."; if (string.IsNullOrWhiteSpace(arr[1])) return "The name transformation pattern is missing."; return null; } catch (Exception e) { return "The parameter is not correct."; } } /// <summary> /// Called whenever a translated file was created in the OUT directory. Its location is: /// {outdirectory}\{locale}\{relativepath} /// When your code shall copy the file to another location, please keep in mind that the relativepath can include directories. /// Example: "chapter\myfile1.doc", "data.xml", etc. /// </summary> /// <param name="projectkey">The project key</param> /// <param name="path">The full path of the created translated file.</param> /// <param name="outdirectory">The "OUT" directory path.</param> /// <param name="targetlocale">The target language code</param> /// <param name="filename">The relative path of the file with respect to {out directory}\{locale}(\){projectfolder}</param> /// <param name="sourcelocale">The source language code</param> /// <param name="configuration">The extension's parameters. You need to implement the respective virtual methods to permit configuring the parameter individually per project.</param> public override void Process( string projectkey, string path, string outdirectory, string targetlocale, string filename, string sourcelocale, IExtensionConfiguration configuration) { string subdirectory, namepattern; // Get parameters var parameter = configuration.Parameter ?? ParameterDefault; var arr = parameter.Split(';'); subdirectory = arr[0].Trim(); namepattern = arr[1].Trim(); // Calculate target path string name = Path.GetFileName(filename); string newname = namepattern .Replace("{name}", Path.GetFileNameWithoutExtension(name)) .Replace("{extension}", Path.GetExtension(name)) .Replace("{tlocale}", targetlocale) .Replace("{slocale}", sourcelocale); string targetPath = Path.Combine(outdirectory, subdirectory, targetlocale, Path.GetDirectoryName(filename), newname); // Ensure that the file's directory exists. If not, create it now. Will raise exception if the target path is invalid. EnsureDirectoryExists(targetPath); // Copy file. May raise exception if the target file cannot be written. File.Copy(path, targetPath, true); } /// <summary> /// Creates all parent directories for the file path if these do not exist. /// </summary> /// <param name="filepath"></param> private static void EnsureDirectoryExists(string filepath) { string d = Path.GetDirectoryName(filepath); if (string.IsNullOrEmpty(d)) throw new Exception(string.Format("The file path '{0}' seems to be invalid. Failed to create all directories.", filepath)); if (!Directory.Exists(d)) { EnsureDirectoryExists(d); Directory.CreateDirectory(d); } } } }
Copyright Wordbee - Buzzin' Outside the Box since 2008