From 64e319869b1155537fc151500eee62f40876b90f Mon Sep 17 00:00:00 2001 From: Ryo Nakano Date: Tue, 13 Feb 2024 21:20:54 +0900 Subject: [PATCH 1/8] valadoc: Application and Define --- src/Application.vala | 26 +++++++++++++++++--------- src/Define.vala | 33 ++++++++++++++++++++++++++++----- 2 files changed, 45 insertions(+), 14 deletions(-) diff --git a/src/Application.vala b/src/Application.vala index 03f58c89..46d02c01 100644 --- a/src/Application.vala +++ b/src/Application.vala @@ -13,12 +13,15 @@ public class Application : Adw.Application { Adw.ColorScheme color_scheme; } + /** + * The instance of the application settings. + */ public static Settings settings { get; private set; } /** * The language name that the user prefers in the system settings, e.g. "en_US", "ja_JP", etc. * - * Used to show the KEY_NAME and KEY_COMMENT in the user's system language. + * Used to show the ``KEY_NAME`` and ``KEY_COMMENT`` in the user's system language. */ public static unowned string preferred_language { get; private set; } @@ -39,13 +42,14 @@ public class Application : Adw.Application { preferred_language = languages[0]; } + /** + * Setup localization, application style, and accel keys. + */ protected override void startup () { base.startup (); - /* - * Make sure the app is shown in the user's language. - * https://docs.gtk.org/glib/i18n.html#internationalization - */ + // Make sure the app is shown in the user's language. + // https://docs.gtk.org/glib/i18n.html#internationalization Intl.setlocale (LocaleCategory.ALL, ""); Intl.bindtextdomain (Config.PROJECT_NAME, Config.LOCALEDIR); Intl.bind_textdomain_codeset (Config.PROJECT_NAME, "UTF-8"); @@ -83,6 +87,12 @@ public class Application : Adw.Application { style_manager.color_scheme = color_scheme; } + /** + * Show {@link MainWindow}. + * + * If there is a instance of {@link MainWindow}, show it and leave the method.<
> + * Otherwise, initialize it, show it, and binding window sizes/states. + */ protected override void activate () { if (main_window != null) { main_window.present (); @@ -97,10 +107,8 @@ public class Application : Adw.Application { settings.bind ("window-height", main_window, "default-height", SettingsBindFlags.DEFAULT); settings.bind ("window-width", main_window, "default-width", SettingsBindFlags.DEFAULT); - /* - * Binding of window maximization with "SettingsBindFlags.DEFAULT" results the window getting bigger and bigger on open. - * So we use the prepared binding only for setting - */ + // Binding of window maximization with "SettingsBindFlags.DEFAULT" results the window getting bigger and bigger on open. + // So we use the prepared binding only for setting bool is_maximized = Application.settings.get_boolean ("window-maximized"); if (is_maximized) { main_window.maximize (); diff --git a/src/Define.vala b/src/Define.vala index e7b97847..8d840fe6 100644 --- a/src/Define.vala +++ b/src/Define.vala @@ -3,25 +3,29 @@ * SPDX-FileCopyrightText: 2021-2024 Ryo Nakano */ +/** + * Defines constants used in the project widely. + */ namespace Define { /** * The name of the application. * - * Use this to prevent the app name from being translated. + * Use this constant to prevent the app name from being translated. */ public const string APP_NAME = "Pin It!"; /** - * A key under g_key_file_desktop_group, whose value is a list of strings giving the keywords which may be used in + * A key under ``g_key_file_desktop_group``, whose value is a list of strings giving the keywords which may be used in * addition to other metadata to describe this entry. * - * Using KeyFileDesktop.KEY_KEYWORDS will cause the cc failing with "‘G_KEY_FILE_DESKTOP_KEY_KEYWORDS’ undeclared" - * error. This constant does not seem to be defined in the original glib and defined in the following patch. + * Using ``KeyFileDesktop.KEY_KEYWORDS`` will cause the cc failing with ``‘G_KEY_FILE_DESKTOP_KEY_KEYWORDS’ undeclared`` + * error.<
> + * This constant does not seem to be defined in the original glib and defined in the following patch.<
> * (and maybe valac uses glibc with this patch and thus it does not complain any error.) * * [[https://sources.debian.org/patches/glib2.0/2.78.3-2/01_gettext-desktopfiles.patch/]] * - * I just keep to borrow the definition of KEY_KEYWORDS here instead of applying the patch, + * We just keep to borrow the definition of KEY_KEYWORDS here instead of applying the patch, * since it might have side effect. */ public const string KEY_KEYWORDS = "Keywords"; @@ -30,10 +34,29 @@ namespace Define { * Defines response IDs used in Adw.MessageDialog. */ namespace DialogResponse { + /** + * Use this constant instead of the literal string ``close``. + */ public const string CLOSE = "close"; + + /** + * Use this constant instead of the literal string ``cancel``. + */ public const string CANCEL = "cancel"; + + /** + * Use this constant instead of the literal string ``ok``. + */ public const string OK = "ok"; + + /** + * Use this constant instead of the literal string ``discard``. + */ public const string DISCARD = "discard"; + + /** + * Use this constant instead of the literal string ``save``. + */ public const string SAVE = "save"; } } From f1a5e9f8e13dcb1ffb9d00667a0b48db5c6926d0 Mon Sep 17 00:00:00 2001 From: Ryo Nakano Date: Sat, 17 Feb 2024 00:08:05 +0900 Subject: [PATCH 2/8] Use Note --- src/Define.vala | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Define.vala b/src/Define.vala index b9a449a5..0256afdb 100644 --- a/src/Define.vala +++ b/src/Define.vala @@ -18,13 +18,13 @@ namespace Define { * A key under ``g_key_file_desktop_group``, whose value is a list of strings giving the keywords which may be used in * addition to other metadata to describe this entry. * - * Using ``KeyFileDesktop.KEY_KEYWORDS`` will cause the cc failing with ``‘G_KEY_FILE_DESKTOP_KEY_KEYWORDS’ undeclared`` + * Note: Using ``KeyFileDesktop.KEY_KEYWORDS`` will cause the cc failing with ``‘G_KEY_FILE_DESKTOP_KEY_KEYWORDS’ undeclared`` * error.<
> * This constant does not seem to be defined in the original glib and defined in the following patch.<
> - * (and maybe valac uses glibc with this patch and thus it does not complain any error.) - * - * [[https://sources.debian.org/patches/glib2.0/2.78.3-2/01_gettext-desktopfiles.patch/]] - * + * (and maybe valac uses glibc with this patch and thus it does not complain any error.)<
> + * <
> + * [[https://sources.debian.org/patches/glib2.0/2.78.3-2/01_gettext-desktopfiles.patch/]]<
> + * <
> * We just keep to borrow the definition of KEY_KEYWORDS here instead of applying the patch, * since it might have side effect. */ From 08402e3e089c4105d913d025b04c4f36e56a4d29 Mon Sep 17 00:00:00 2001 From: Ryo Nakano Date: Sat, 17 Feb 2024 00:11:09 +0900 Subject: [PATCH 3/8] Lessen space --- src/Define.vala | 26 ++++++-------------------- 1 file changed, 6 insertions(+), 20 deletions(-) diff --git a/src/Define.vala b/src/Define.vala index 0256afdb..f15c7cb7 100644 --- a/src/Define.vala +++ b/src/Define.vala @@ -31,32 +31,18 @@ namespace Define { public const string KEY_KEYWORDS = "Keywords"; /** - * Defines response IDs used in Adw.MessageDialog. + * Response IDs used in Adw.MessageDialog. */ namespace DialogResponse { - /** - * Use this constant instead of the literal string ``close``. - */ + /** Use this constant instead of the literal string ``close``. */ public const string CLOSE = "close"; - - /** - * Use this constant instead of the literal string ``cancel``. - */ + /** Use this constant instead of the literal string ``cancel``. */ public const string CANCEL = "cancel"; - - /** - * Use this constant instead of the literal string ``ok``. - */ + /** Use this constant instead of the literal string ``ok``. */ public const string OK = "ok"; - - /** - * Use this constant instead of the literal string ``discard``. - */ + /** Use this constant instead of the literal string ``discard``. */ public const string DISCARD = "discard"; - - /** - * Use this constant instead of the literal string ``save``. - */ + /** Use this constant instead of the literal string ``save``. */ public const string SAVE = "save"; } From af9d7ecc4aa5fa4dd5bb6a7737495193bd5c6e74 Mon Sep 17 00:00:00 2001 From: Ryo Nakano Date: Sat, 17 Feb 2024 09:12:48 +0900 Subject: [PATCH 4/8] DesktopFileModel: Update doc --- src/Model/DesktopFileModel.vala | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/src/Model/DesktopFileModel.vala b/src/Model/DesktopFileModel.vala index cff72fa8..201d9749 100644 --- a/src/Model/DesktopFileModel.vala +++ b/src/Model/DesktopFileModel.vala @@ -8,7 +8,7 @@ */ /** - * The class to load desktop files and stores in the form of {@link DesktopFile} class. + * The class to load desktop files and store them in the type of {@link DesktopFile}. */ public class Model.DesktopFileModel : Object { /** @@ -27,7 +27,7 @@ public class Model.DesktopFileModel : Object { public ListStore files_list { get; private set; } /** - * The representation of the {@link desktop_files_path} in the File type. + * The directory where user desktop files are stored. */ private File desktop_files_dir; @@ -51,14 +51,12 @@ public class Model.DesktopFileModel : Object { } /** - * Search for desktop files and stores in the {@link DesktopFile} data type. + * Search for desktop files and store in the {@link DesktopFile} data type. * - * Search ~/.local/share/applications for files with .desktop suffix. Create a new - * {@link DesktopFile} if a matching file found and is valid. Repeat this for all files in the directory - * and then return the list of {@link DesktopFile}. + * Search ``~/.local/share/applications`` for files with .desktop suffix. Create a new + * {@link DesktopFile} if a matching file found and is valid. Repeat this for all files in the directory. * - * Emits {@link DesktopFileModel.load_success} if loaded successfully, {@link DesktopFileModel.load_failure} - * otherwise. + * Emits {@link load_success} if loaded successfully, {@link load_failure} otherwise. */ public void load () { files_list.remove_all (); @@ -67,9 +65,9 @@ public class Model.DesktopFileModel : Object { var enumerator = desktop_files_dir.enumerate_children (FileAttribute.STANDARD_NAME, FileQueryInfoFlags.NONE); FileInfo file_info = null; - // Check and address the files in the desktop_files_path directory one by one + // Check all files in the directory one by one while ((file_info = enumerator.next_file ()) != null) { - // We handle only the desktop file in this app, so ignore any files without the .desktop suffix + // Ignore any files without the .desktop suffix string name = file_info.get_name (); if (!name.has_suffix (DesktopFile.DESKTOP_SUFFIX)) { continue; From 52c27fa7bf8a38f0f851f367234d8e1af6d30696 Mon Sep 17 00:00:00 2001 From: Ryo Nakano Date: Sat, 17 Feb 2024 09:39:51 +0900 Subject: [PATCH 5/8] DesktopFile: valadoc --- src/Model/DesktopFile.vala | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/src/Model/DesktopFile.vala b/src/Model/DesktopFile.vala index 2e757dfb..9acc2129 100644 --- a/src/Model/DesktopFile.vala +++ b/src/Model/DesktopFile.vala @@ -8,21 +8,24 @@ */ public class Model.DesktopFile : Object { /** - * The path of the desktop file. + * The absolute path to the desktop file. */ public string path { get; construct; } /** - * The prefix of the desktop file. + * The suffix of the desktop files. */ public const string DESKTOP_SUFFIX = ".desktop"; + /** + * Store data in a single desktop file. + */ private KeyFile keyfile; /** * The constructor. * - * @param path The path to the desktop file. + * @param path The absolute path to the desktop file. */ public DesktopFile (string path) { Object ( @@ -35,7 +38,7 @@ public class Model.DesktopFile : Object { } /** - * Returns true if this and other contains the same values. + * Check if this and other contains the same values as desktop files. * * @param other Another DesktopFile. * @return true if this and other contains the same values. @@ -65,6 +68,15 @@ public class Model.DesktopFile : Object { // //////////////////////////////////////////////////////////////////////////// + /** + * Return the value associated with ``key`` as a boolean. + * + * @param key a key + * @param is_required whether this key is required as + * [[https://specifications.freedesktop.org/desktop-entry-spec/desktop-entry-spec-latest.html|Desktop Entry Specification]]. + * @return the value associated with the key as a boolean, or false if the key was not found or could not be parsed. + * @see GLib.KeyFile.get_boolean + */ public bool get_boolean (string key, bool is_required = true) { bool val = false; @@ -298,7 +310,7 @@ public class Model.DesktopFile : Object { } /** - * Open this in an external editor. + * Open the desktop file associated with this in an external editor. * * @return true if successfully opened this, false otherwise. */ From f268266985a8b66d07ca44475ddba317b024734e Mon Sep 17 00:00:00 2001 From: Ryo Nakano Date: Sun, 18 Feb 2024 10:18:31 +0900 Subject: [PATCH 6/8] Complete documentation for Application --- src/Application.vala | 81 ++++++++++++++++++++++++++++++++++++++------ 1 file changed, 70 insertions(+), 11 deletions(-) diff --git a/src/Application.vala b/src/Application.vala index 28b430f0..4fb866a9 100644 --- a/src/Application.vala +++ b/src/Application.vala @@ -3,7 +3,13 @@ * SPDX-FileCopyrightText: 2021-2024 Ryo Nakano */ +/** + * The foundation class to manage the app and its window. + */ public class Application : Adw.Application { + /** + * Action names and their callbacks. + */ private const ActionEntry[] ACTION_ENTRIES = { { "quit", on_quit_activate }, }; @@ -20,6 +26,9 @@ public class Application : Adw.Application { */ public static unowned string preferred_language { get; private set; } + /** + * The instance of the app window. + */ private MainWindow main_window; public Application () { @@ -37,6 +46,16 @@ public class Application : Adw.Application { preferred_language = languages[0]; } + /** + * Convert ``from_value`` to ``to_value``. + * + * @param binding a binding + * @param from_value the value of Action.state property + * @param to_value the value of Adw.StyleManager.color_scheme property + * @return true if the transformation was successful, false otherwise + * + * @see GLib.BindingTransformFunc + */ private bool style_action_transform_to_cb (Binding binding, Value from_value, ref Value to_value) { Variant? variant = from_value.dup_variant (); if (variant == null) { @@ -59,6 +78,16 @@ public class Application : Adw.Application { return true; } + /** + * Convert ``from_value`` to ``to_value``. + * + * @param binding a binding + * @param from_value the value of Adw.StyleManager.color_scheme property + * @param to_value the value of Action.state property + * @return true if the transformation was successful, false otherwise + * + * @see GLib.BindingTransformFunc + */ private bool style_action_transform_from_cb (Binding binding, Value from_value, ref Value to_value) { var val = (Adw.ColorScheme) from_value; switch (val) { @@ -75,18 +104,27 @@ public class Application : Adw.Application { return true; } - private static bool color_scheme_get_mapping_cb (Value value, Variant variant, void* user_data) { - // Convert from the "style" enum defined in the gschema to Adw.ColorScheme - var val = variant.get_string (); + /** + * Convert from the "style" enum defined in the gschema to Adw.ColorScheme. + * + * @param to_value return location for the "color-scheme" property value of ``style_manager`` + * @param from_variant the Variant containing "style" enum value of {@link settings} + * @param user_data unused (null) + * @return true if the conversion succeeded, false otherwise + * + * @see GLib.SettingsBindGetMappingShared + */ + private static bool color_scheme_get_mapping_cb (Value to_value, Variant from_variant, void* user_data) { + var val = from_variant.get_string (); switch (val) { case Define.Style.DEFAULT: - value.set_enum (Adw.ColorScheme.DEFAULT); + to_value.set_enum (Adw.ColorScheme.DEFAULT); break; case Define.Style.LIGHT: - value.set_enum (Adw.ColorScheme.FORCE_LIGHT); + to_value.set_enum (Adw.ColorScheme.FORCE_LIGHT); break; case Define.Style.DARK: - value.set_enum (Adw.ColorScheme.FORCE_DARK); + to_value.set_enum (Adw.ColorScheme.FORCE_DARK); break; default: warning ("color_scheme_get_mapping_cb: Invalid style: %s", val); @@ -96,11 +134,20 @@ public class Application : Adw.Application { return true; } - private static Variant color_scheme_set_mapping_cb (Value value, VariantType expected_type, void* user_data) { + /** + * Convert from Adw.ColorScheme to the "style" enum defined in the gschema. + * + * @param from_value the "color-scheme" property value of ``style_manager`` + * @param expected_type the expected type of Variant that this method returns + * @param user_data unused (null) + * @return a new Variant holding the data from ``from_value`` + * + * @see GLib.SettingsBindSetMappingShared + */ + private static Variant color_scheme_set_mapping_cb (Value from_value, VariantType expected_type, void* user_data) { string color_scheme; - // Convert from Adw.ColorScheme to the "style" enum defined in the gschema - var val = (Adw.ColorScheme) value; + var val = (Adw.ColorScheme) from_value; switch (val) { case Adw.ColorScheme.DEFAULT: color_scheme = Define.Style.DEFAULT; @@ -121,6 +168,13 @@ public class Application : Adw.Application { return new Variant.string (color_scheme); } + /** + * Make it possible to change the app style with the following action names + * and remember that preference to {@link settings}. + * + * You can change the app style by passsing Adw.ColorScheme value as a target value + * to the ``app.color-scheme`` action. + */ private void setup_style () { var style_action = new SimpleAction.stateful ( "color-scheme", VariantType.INT32, new Variant.int32 (Adw.ColorScheme.DEFAULT) @@ -137,7 +191,7 @@ public class Application : Adw.Application { } /** - * Setup localization, application style, and accel keys. + * Setup localization, app style, and accel keys. */ protected override void startup () { base.startup (); @@ -159,7 +213,7 @@ public class Application : Adw.Application { /** * Show {@link MainWindow}. * - * If there is a instance of {@link MainWindow}, show it and leave the method.<
> + * If there is an instance of {@link MainWindow}, show it and leave the method.<
> * Otherwise, initialize it, show it, and binding window sizes/states. */ protected override void activate () { @@ -186,6 +240,11 @@ public class Application : Adw.Application { settings.bind ("window-maximized", main_window, "maximized", SettingsBindFlags.SET); } + /** + * The callback for "app.quit" action. + * + * Perform pre-destruction process if there is an instance of {@link MainWindow}, otherwise quit the app immediately. + */ private void on_quit_activate () { if (main_window != null) { main_window.prep_destroy (); From 962b91ec99fcd1bda42eea78515feb106fbbe23d Mon Sep 17 00:00:00 2001 From: Ryo Nakano Date: Sun, 18 Feb 2024 14:02:01 +0900 Subject: [PATCH 7/8] No case and trailing period --- src/Model/DesktopFile.vala | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/Model/DesktopFile.vala b/src/Model/DesktopFile.vala index 9acc2129..92aeb754 100644 --- a/src/Model/DesktopFile.vala +++ b/src/Model/DesktopFile.vala @@ -25,7 +25,7 @@ public class Model.DesktopFile : Object { /** * The constructor. * - * @param path The absolute path to the desktop file. + * @param path the absolute path to the desktop file */ public DesktopFile (string path) { Object ( @@ -40,8 +40,8 @@ public class Model.DesktopFile : Object { /** * Check if this and other contains the same values as desktop files. * - * @param other Another DesktopFile. - * @return true if this and other contains the same values. + * @param other another DesktopFile + * @return true if this and other contains the same values */ public bool equals (DesktopFile other) { // Compare other than the path @@ -54,8 +54,8 @@ public class Model.DesktopFile : Object { /** * Copy and set data from this to another DesktopFile. * - * @param dest Another DesktopFile to copy this data to. - * @return true if successfully copied, false otherwise. + * @param dest another DesktopFile to copy this data to + * @return true if successfully copied, false otherwise */ public bool copy_to (DesktopFile dest) { string data = to_data (); @@ -72,9 +72,9 @@ public class Model.DesktopFile : Object { * Return the value associated with ``key`` as a boolean. * * @param key a key - * @param is_required whether this key is required as - * [[https://specifications.freedesktop.org/desktop-entry-spec/desktop-entry-spec-latest.html|Desktop Entry Specification]]. - * @return the value associated with the key as a boolean, or false if the key was not found or could not be parsed. + * @param is_required whether this key is required in + * [[https://specifications.freedesktop.org/desktop-entry-spec/desktop-entry-spec-latest.html|Desktop Entry Specification]] + * @return the value associated with the key as a boolean, or false if the key was not found or could not be parsed * @see GLib.KeyFile.get_boolean */ public bool get_boolean (string key, bool is_required = true) { @@ -312,7 +312,7 @@ public class Model.DesktopFile : Object { /** * Open the desktop file associated with this in an external editor. * - * @return true if successfully opened this, false otherwise. + * @return true if successfully opened this, false otherwise */ public bool open_external () { return Util.ExternalAppLauncher.open_default_handler (path); From a09609f9906a9fe89c138c840f11b889199335de Mon Sep 17 00:00:00 2001 From: Ryo Nakano Date: Sun, 3 Mar 2024 15:33:38 +0900 Subject: [PATCH 8/8] Add documentation of MainWindow --- src/MainWindow.vala | 37 ++++++++++++++++++++++++++++++------- 1 file changed, 30 insertions(+), 7 deletions(-) diff --git a/src/MainWindow.vala b/src/MainWindow.vala index 1d174d3e..e2cff9a8 100644 --- a/src/MainWindow.vala +++ b/src/MainWindow.vala @@ -3,6 +3,23 @@ * SPDX-FileCopyrightText: 2021-2024 Ryo Nakano */ +/** + * The window of the application. + * + * It contains a ``Adw.NavigationSplitView`` as a view which has a {@link View.FilesView} and + * {@link View.EditView} inside. + * + * It also has a instance of {@link Model.DesktopFileModel} and calls {@link Model.DesktopFileModel.load} when: + * + * * constructed + * * {@link View.FilesView.deleted} is emitted + * * {@link View.EditView.saved} is emitted + * * the action ``win.new`` is called + * + * If {@link Model.DesktopFileModel.load} succeeded, this calls {@link View.FilesView.set_list_data} to reflect + * load result.<
> + * Otherwise, this shows a dialog to tell the user about the failure. + */ public class MainWindow : Adw.ApplicationWindow { private const ActionEntry[] ACTION_ENTRIES = { { "about", on_about_activate }, @@ -100,7 +117,7 @@ public class MainWindow : Adw.ApplicationWindow { /** * The callback when loading the list of desktop files failed. * - * Tell the user the failure through the dialog. + * Tell the user the failure through a dialog. */ private void on_load_failure () { var error_dialog = new Adw.MessageDialog (this, @@ -124,7 +141,7 @@ public class MainWindow : Adw.ApplicationWindow { * Preprocess before destruction of this. * * Just destroy this if we never edited entries or no changes made for desktop files. - * Otherwise, tell the user unsaved work through dialog. + * Otherwise, tell the user unsaved work through a dialog. */ public void prep_destroy () { // Never edited entries @@ -173,9 +190,12 @@ public class MainWindow : Adw.ApplicationWindow { } /** - * Start editing the given DesktopFile + * Start editing the given {@link Model.DesktopFile}. + * + * It first backups the given {@link Model.DesktopFile} and then calls {@link View.EditView.load_file} to start + * editing, so that the app can recognize unsaved changes before destruction. * - * @param file The DesktopFile to edit. + * @param file The {@link Model.DesktopFile} to edit */ public void show_edit_view (Model.DesktopFile file) { desktop_file = file; @@ -211,12 +231,12 @@ public class MainWindow : Adw.ApplicationWindow { * The callback for about window. */ private void on_about_activate () { - // List code contributors + // List of code contributors const string[] DEVELOPERS = { "Ryo Nakano https://github.com/ryonakano", "Jeyson Flores https://github.com/JeysonFlores", }; - // List icon authors + // List of icon authors const string[] ARTISTS = { "hanaral https://github.com/hanaral", }; @@ -236,7 +256,10 @@ public class MainWindow : Adw.ApplicationWindow { developer_name = "Ryo Nakano", developers = DEVELOPERS, artists = ARTISTS, - ///TRANSLATORS: Replace with your name; don't translate literally + ///TRANSLATORS: A newline-separated list of translators. Don't translate literally. + ///You may add your name and your email address/website URL if you want, e.g.: + ///John Doe + ///Jane Doe translator_credits = _("translator-credits") };