Move menus+tools strings to en.ini file (#124)

This commit is contained in:
David Capello 2017-10-11 18:02:38 -03:00
parent f4ffd4110c
commit 36a44e6691
17 changed files with 737 additions and 409 deletions

File diff suppressed because it is too large Load Diff

View File

@ -22,6 +22,21 @@ extras = Extras:
shade = Shade
pixel_perfect = Pixel-Perfect
[cel_movement_popup_menu]
move = &Move
copy = &Copy
cancel = Cancel
[cel_popup_menu]
clear = &Clear
unlink = &Unlink
link_cels = &Link Cels
[document_tab_popup_menu]
duplicate_view = Duplicate &View
open_with_os = &Open with OS
open_in_folder = Open in &Folder
[canvas_size]
title = Canvas Size
size = Size:
@ -185,6 +200,14 @@ partial_tiles = Include partial tiles at bottom/right edges
import = &Import
cancel = &Cancel
[ink_popup_menu]
simple_ink = Simple Ink
alpha_compositing = Alpha Compositing
copy_color = Copy Alpha+Color
lock_alpha = Lock Alpha
shading = Shading
same_in_all_tools = Same in all Tools
[jpeg_options]
title = JPEG Options
quality = Quality:
@ -203,6 +226,160 @@ name = Name:
mode = Mode:
opacity = Opacity:
[main_menu]
file = &File
file_new = &New...
file_open = &Open...
file_open_recent = Open &Recent
file_save = &Save
file_save_as = Save &As...
file_export = Expor&t...
file_close = &Close
file_close_all = Close All
file_import_sprite_sheet = &Import Sprite Sheet
file_export_sprite_sheet = &Export Sprite Sheet
file_repeat_last_export = Repeat &Last Export
file_exit = E&xit
edit = &Edit
edit_undo = &Undo
edit_redo = &Redo
edit_undo_history = Undo Histor&y
edit_cut = Cu&t
edit_copy = &Copy
edit_copy_merged = Copy Mer&ged
edit_paste = &Paste
edit_clear = C&lear
edit_rotate = R&otate
edit_rotate_180 = &180
edit_rotate_90cw = &90 CW
edit_rotate_90ccw = 90 &CCW
edit_flip_horizontal = Flip &Horizontal
edit_flip_vertical = Flip &Vertical
edit_transform = Transfor&m
edit_shift = &Shift
edit_shift_left = &Left
edit_shift_right = &Right
edit_shift_up = &Up
edit_shift_down = &Down
edit_new_brush = New &Brush
edit_new_sprite_from_selection = &New Sprite from Selection
edit_replace_color = R&eplace Color...
edit_invert_color = &Invert...
edit_adjustments = Ad&justments
edit_adjustments_brightness_contrast = &Brightness/Contrast...
edit_adjustments_hue_saturation = &Hue/Saturation...
edit_adjustments_color_curve = &Color Curve...
edit_fx = F&X
edit_fx_convolution_matrix = Convolution &Matrix...
edit_fx_despeckle = &Despeckle (Median Filter)...
edit_insert_text = Insert Text
edit_keyboard_shortcuts = &Keyboard Shortcuts...
edit_preferences = Pre&ferences...
sprite = &Sprite
sprite_properties = &Properties...
sprite_color_mode = Color &Mode
sprite_color_mode_rgb = &RGB Color
sprite_color_mode_grayscale = &Grayscale
sprite_color_mode_indexed = &Indexed
sprite_color_mode_more_options = &More Options
sprite_duplicate = &Duplicate...
sprite_sprite_size = &Sprite Size...
sprite_canvas_size = &Canvas Size...
sprite_rotate_canvas = &Rotate Canvas
sprite_rotate = R&otate
sprite_rotate_180 = &180
sprite_rotate_90cw = &90 CW
sprite_rotate_90ccw = 90 &CCW
sprite_flip_canvas_horizontal = Flip Canvas &Horizontal
sprite_flip_canvas_vertical = Flip Canvas &Vertical
sprite_crop = Cr&op
sprite_trim = &Trim
layer = &Layer
layer_properties = &Properties...
layer_visible = &Visible
layer_lock_layers = Loc&k Layers
layer_open_group = &Open Group
layer_new_layer = &New Layer
layer_new_group = New &Group
layer_delete_layer = Delete Laye&r
layer_background_from_layer = &Background from Layer
layer_layer_from_background = &Layer from Background
layer_duplicate = &Duplicate
layer_merge_down = &Merge Down
layer_flatten = &Flatten
layer_add_reference_layer = Add R&eference Layer
frame = F&rame
frame_properties = Frame &Properties...
frame_cel_properties = &Cel Properties...
frame_new_frame = &New Frame
frame_new_empty_frame = New &Empty Frame
frame_duplicate_cels = &Duplicate Cel(s)
frame_duplicate_linked_cels = Duplicate &Linked Cel(s)
frame_delete_frame = Delete F&rame
frame_tags = &Tags
frame_tags_tag_properties = Tag &Properties...
frame_tags_new_tag = New &Tag
frame_tags_delete_tag = &Delete Tag
frame_jump_to = &Jump to
frame_jump_to_first_frame = &First Frame
frame_jump_to_previous_frame = &Previous Frame
frame_jump_to_next_frame = &Next Frame
frame_jump_to_last_frame = &Last Frame
frame_go_to_frame = &Go to Frame
frame_play_animation = &Play Animation
frame_constant_frame_rate = Constant Frame Rate
frame_reverse_frames = Re&verse Frames
select = Selec&t
select_all = &All
select_deselect = &Deselect
select_reselect = &Reselect
select_inverse = &Inverse
select_color_range = &Color Range
select_modify = &Modify
select_modify_border = &Border
select_modify_expand = &Expand
select_modify_contract = &Contract
select_load_from_file = &Load from MSK file
select_save_to_file = &Save to MSK file
view = &View
view_duplicate_view = Duplicate &View
view_show_extras = &Extras
view_show = &Show
view_show_layer_edges = &Layer Edges
view_show_selection_edges = &Selection Edges
view_show_grid = &Grid
view_show_auto_guides = &Auto Guides
view_show_slices = Sl&ices
view_show_pixel_grid = &Pixel Grid
view_show_brush_preview = &Brush Preview
view_grid = &Grid
view_grid_settings = Gri&d Settings
view_grid_selection_as_grid = Select&ion as Grid
view_grid_snap_to_grid = &Snap to Grid
view_tiled_mode = Tiled &Mode
view_tiled_mode_none = &None
view_tiled_mode_both = Tiled in &Both Axes
view_tiled_mode_x = Tiled in &X Axis
view_tiled_mode_y = Tiled in &Y Axis
view_symmetry_options = S&ymmetry Options
view_set_loop_section = Set &Loop Section
view_show_onion_skin = Show &Onion Skin
view_timeline = &Timeline
view_preview = Previe&w
view_full_screen_mode = &Full Screen Mode
view_full_screen_preview = F&ull Screen Preview
view_home = &Home
view_refresh = &Refresh && Reload Skin
help = &Help
help_readme = Readme
help_quick_reference = Quick &Reference
help_documentation = Documentation
help_tutorial = Tutorial
help_release_notes = Release Notes
help_twitter = Twitter
help_donate = &Donate
help_about = &About
[modify_selection]
title = Modify Selection
circle = Circle Brush
@ -434,6 +611,22 @@ alpha_channel = Create entries with alpha component
load = &Load
open_folder = Open &Folder
[palette_popup_menu]
edit_palette = Edit &Palette
palette_size = Palette Si&ze
small_size = &Small Size
medium_size = &Medium Size
large_size = &Large Size
color_tint_shade_tone = Color Tint/Shade/Tone
color_spectrum = Color Spectrum
rgb_color_wheel = RGB Color Wheel
ryb_color_wheel = RYB Color Wheel
load_palette = L&oad Palette
save_palette = S&ave Palette
load_default_palette = Load Default Palette
save_as_default_palette = Save as Default Palette
create_palette_from_current_sprite = Create Palette from Current Sprite
[palette_size]
title = Palette Size
number_of_colors = Number of colors:
@ -478,6 +671,10 @@ open_dmp_file = Open the following file to debug your compilation:
do_it_later = Do it later
delete_file = Delete file, I've already sent it
[slice_popup_menu]
properties = Slice &Properties...
delete = &Delete Slice
[slice_properties]
title = Slice Properties
name = Slice Name:
@ -528,6 +725,9 @@ percentage = Percentage:
interpolation = Interpolation:
method = Method:
[tab_popup_menu]
close = &Close
[timeline_conf]
position = Position:
left = &Left
@ -556,6 +756,58 @@ END
in_front = In front of sprite
in_front_toolip = For all kind of layers (background and transparents)
[tools]
rectangular_marquee = Rectangular Marquee Tool
rectangular_marquee_tooltip = <<<END
* Left-button: replace/add to current selection.
* Right-button: remove from current selection.
END
elliptical_marquee = Elliptical Marquee Tool
elliptical_marquee_tooltip = <<<END
* Left-button: Replace/add to current selection.
* Right-button: Remove from current selection.
END
lasso_tool = Lasso Tool
lasso_tool_tooltip = <<<END
* Left-button: Replace/add to current selection.
* Right-button: Remove from current selection.
END
polygonal_lasso = Polygonal Lasso Tool
polygonal_lasso_tooltip = <<<END
* Left-button: Replace/add to current selection.
* Right-button: Remove from current selection.
END
magic_wand = Magic Wand Tool
magic_wand_tooltip = <<<END
* Left-button: Replace/add to current selection.
* Right-button: Remove from current selection.
END
pencil = Pencil Tool
spray = Spray Tool
eraser = Eraser Tool
eraser_tooltip = <<<END
* Left-button: Erase with the background color in 'Background' layer
or transparent color in any other layer.
* Right-button: Replace foreground with background color.
END
eyedropper = Eyedropper Tool
zoom = Zoom Tool
hand = Hand Tool
move = Move Tool
slice = Slice Tool
paint_bucket = Paint Bucket Tool
gradient = Gradient Tool
line = Line Tool
curve = Curve Tool
rectangle = Rectangle Tool
filled_rectangle = Filled Rectangle Tool
ellipse = Ellipse Tool
filled_ellipse = Filled Ellipse Tool
contour = Contour Tool
polygon = Polygon Tool
blur = Blur Tool
jumble = Jumble Tool
[undo_history]
title = Undo History

View File

@ -70,9 +70,9 @@ file(GLOB string_files ${CMAKE_SOURCE_DIR}/data/strings/*.ini)
set(output_fn ${CMAKE_CURRENT_BINARY_DIR}/check-translations.txt)
add_custom_command(
OUTPUT ${output_fn}
COMMAND ${CMAKE_BINARY_DIR}/bin/gen --widgets-dir "${CMAKE_SOURCE_DIR}/data/widgets/" --strings-dir "${CMAKE_SOURCE_DIR}/data/strings/" >${output_fn}
COMMAND ${CMAKE_BINARY_DIR}/bin/gen --widgets-dir "${CMAKE_SOURCE_DIR}/data/widgets/" --strings-dir "${CMAKE_SOURCE_DIR}/data/strings/" --gui-file "${CMAKE_SOURCE_DIR}/data/gui.xml" >${output_fn}
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
DEPENDS gen ${widget_files} ${string_files})
DEPENDS gen ${widget_files} ${string_files} "${CMAKE_SOURCE_DIR}/data/gui.xml")
list(APPEND generated_files ${output_fn})
# Directory where generated files by "gen" utility will stay.
@ -389,6 +389,7 @@ add_library(app-lib
font_path.cpp
gui_xml.cpp
i18n/strings.cpp
i18n/xml_translator.cpp
ini_file.cpp
job.cpp
launcher.cpp

View File

@ -16,6 +16,7 @@
#include "app/commands/params.h"
#include "app/console.h"
#include "app/gui_xml.h"
#include "app/i18n/strings.h"
#include "app/recent_files.h"
#include "app/resource_finder.h"
#include "app/tools/tool_box.h"
@ -327,16 +328,16 @@ void AppMenus::reload()
LOG("MENU: Main menu loaded.\n");
m_tabPopupMenu.reset(loadMenuById(handle, "tab_popup"));
m_documentTabPopupMenu.reset(loadMenuById(handle, "document_tab_popup"));
m_layerPopupMenu.reset(loadMenuById(handle, "layer_popup"));
m_framePopupMenu.reset(loadMenuById(handle, "frame_popup"));
m_celPopupMenu.reset(loadMenuById(handle, "cel_popup"));
m_celMovementPopupMenu.reset(loadMenuById(handle, "cel_movement_popup"));
m_frameTagPopupMenu.reset(loadMenuById(handle, "frame_tag_popup"));
m_slicePopupMenu.reset(loadMenuById(handle, "slice_popup"));
m_palettePopupMenu.reset(loadMenuById(handle, "palette_popup"));
m_inkPopupMenu.reset(loadMenuById(handle, "ink_popup"));
m_tabPopupMenu.reset(loadMenuById(handle, "tab_popup_menu"));
m_documentTabPopupMenu.reset(loadMenuById(handle, "document_tab_popup_menu"));
m_layerPopupMenu.reset(loadMenuById(handle, "layer_popup_menu"));
m_framePopupMenu.reset(loadMenuById(handle, "frame_popup_menu"));
m_celPopupMenu.reset(loadMenuById(handle, "cel_popup_menu"));
m_celMovementPopupMenu.reset(loadMenuById(handle, "cel_movement_popup_menu"));
m_frameTagPopupMenu.reset(loadMenuById(handle, "frame_tag_popup_menu"));
m_slicePopupMenu.reset(loadMenuById(handle, "slice_popup_menu"));
m_palettePopupMenu.reset(loadMenuById(handle, "palette_popup_menu"));
m_inkPopupMenu.reset(loadMenuById(handle, "ink_popup_menu"));
createNativeMenus();
@ -439,10 +440,12 @@ Menu* AppMenus::loadMenuById(TiXmlHandle& handle, const char* id)
.FirstChild("menus")
.FirstChild("menu").ToElement();
while (xmlMenu) {
const char* menu_id = xmlMenu->Attribute("id");
const char* menuId = xmlMenu->Attribute("id");
if (menu_id && strcmp(menu_id, id) == 0)
if (menuId && strcmp(menuId, id) == 0) {
m_xmlTranslator.setStringIdPrefix(menuId);
return convertXmlelemToMenu(xmlMenu);
}
xmlMenu = xmlMenu->NextSiblingElement();
}
@ -496,7 +499,8 @@ Widget* AppMenus::convertXmlelemToMenuitem(TiXmlElement* elem)
}
// Create the item
AppMenuItem* menuitem = new AppMenuItem(elem->Attribute("text"), command, params);
AppMenuItem* menuitem = new AppMenuItem(m_xmlTranslator(elem, "text"),
command, params);
if (!menuitem)
return nullptr;

View File

@ -8,6 +8,8 @@
#define APP_APP_MENUS_H_INCLUDED
#pragma once
#include "app/i18n/xml_translator.h"
#include "app/widget_type_mismatch.h"
#include "base/disable_copying.h"
#include "base/unique_ptr.h"
#include "obs/connection.h"
@ -88,6 +90,7 @@ namespace app {
obs::scoped_connection m_recentFilesConn;
std::vector<Menu*> m_menus;
she::Menu* m_osMenu;
XmlTranslator m_xmlTranslator;
};
she::Shortcut get_os_shortcut_from_key(Key* key);

View File

@ -0,0 +1,44 @@
// Aseprite
// Copyright (C) 2017 David Capello
//
// This program is distributed under the terms of
// the End-User License Agreement for Aseprite.
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "app/i18n/xml_translator.h"
#include "app/i18n/strings.h"
#include "tinyxml.h"
namespace app {
std::string XmlTranslator::operator()(const TiXmlElement* elem,
const char* attrName)
{
const char* value = elem->Attribute(attrName);
if (!value)
return std::string();
else if (value[0] == '@') {
if (value[1] == '.')
return Strings::instance()->translate((m_stringIdPrefix + (value+1)).c_str());
else
return Strings::instance()->translate(value+1);
}
else
return std::string(value);
}
void XmlTranslator::clearStringIdPrefix()
{
m_stringIdPrefix.clear();
}
void XmlTranslator::setStringIdPrefix(const char* prefix)
{
m_stringIdPrefix = prefix;
}
} // namespace app

View File

@ -0,0 +1,31 @@
// Aseprite
// Copyright (C) 2017 David Capello
//
// This program is distributed under the terms of
// the End-User License Agreement for Aseprite.
#ifndef APP_I18N_XML_TRANSLATOR_INCLUDED
#define APP_I18N_XML_TRANSLATOR_INCLUDED
#pragma once
#include <string>
class TiXmlElement;
namespace app {
class XmlTranslator {
public:
std::string operator()(const TiXmlElement* elem,
const char* attrName);
void clearStringIdPrefix();
void setStringIdPrefix(const char* prefix);
private:
std::string m_stringIdPrefix;
};
} // namespace app
#endif

View File

@ -11,6 +11,7 @@
#include "app/tools/tool_box.h"
#include "app/gui_xml.h"
#include "app/i18n/strings.h"
#include "app/tools/controller.h"
#include "app/tools/ink.h"
#include "app/tools/intertwine.h"
@ -92,6 +93,8 @@ const char* WellKnownPointShapes::Spray = "spray";
ToolBox::ToolBox()
{
m_xmlTranslator.setStringIdPrefix("tools");
m_inks[WellKnownInks::Selection] = new SelectionInk();
m_inks[WellKnownInks::Paint] = new PaintInk(PaintInk::Simple);
m_inks[WellKnownInks::PaintFg] = new PaintInk(PaintInk::WithFg);
@ -194,29 +197,27 @@ void ToolBox::loadTools()
// For each group
TiXmlElement* xmlGroup = handle.FirstChild("gui").FirstChild("tools").FirstChild("group").ToElement();
while (xmlGroup) {
const char* group_id = xmlGroup->Attribute("id");
const char* group_text = xmlGroup->Attribute("text");
if (!group_id || !group_text)
const char* groupId = xmlGroup->Attribute("id");
if (!groupId)
throw base::Exception("The configuration file has a <group> without 'id' or 'text' attributes.");
LOG(VERBOSE) << "TOOL: Group " << group_id << "\n";
LOG(VERBOSE) << "TOOL: Group " << groupId << "\n";
ToolGroup* tool_group = new ToolGroup(group_id, group_text);
ToolGroup* toolGroup = new ToolGroup(groupId);
// For each tool
TiXmlNode* xmlToolNode = xmlGroup->FirstChild("tool");
TiXmlElement* xmlTool = xmlToolNode ? xmlToolNode->ToElement(): NULL;
while (xmlTool) {
const char* tool_id = xmlTool->Attribute("id");
const char* tool_text = xmlTool->Attribute("text");
const char* tool_tips = xmlTool->FirstChild("tooltip") ? ((TiXmlElement*)xmlTool->FirstChild("tooltip"))->GetText(): "";
const char* default_brush_size = xmlTool->Attribute("default_brush_size");
const char* toolId = xmlTool->Attribute("id");
std::string toolText = m_xmlTranslator(xmlTool, "text");
std::string toolTips = m_xmlTranslator(xmlTool, "tooltip");
const char* defaultBrushSize = xmlTool->Attribute("default_brush_size");
Tool* tool = new Tool(tool_group, tool_id, tool_text, tool_tips,
default_brush_size ? strtol(default_brush_size, NULL, 10): 1);
Tool* tool = new Tool(toolGroup, toolId, toolText, toolTips,
defaultBrushSize ? strtol(defaultBrushSize, NULL, 10): 1);
LOG(VERBOSE) << "TOOL: Tool " << tool_id << " in group " << group_id << " found\n";
LOG(VERBOSE) << "TOOL: Tool " << toolId << " in group " << groupId << " found\n";
loadToolProperties(xmlTool, tool, 0, "left");
loadToolProperties(xmlTool, tool, 1, "right");
@ -226,7 +227,7 @@ void ToolBox::loadTools()
xmlTool = xmlTool->NextSiblingElement();
}
m_groups.push_back(tool_group);
m_groups.push_back(toolGroup);
xmlGroup = xmlGroup->NextSiblingElement();
}

View File

@ -12,6 +12,7 @@
#include <map>
#include <string>
#include "app/i18n/xml_translator.h"
#include "app/tools/tool.h"
#include "base/unique_ptr.h"
@ -117,6 +118,7 @@ namespace app {
ToolGroupList m_groups;
ToolList m_tools;
XmlTranslator m_xmlTranslator;
};
} // namespace tools

View File

@ -1,5 +1,5 @@
// Aseprite
// Copyright (C) 2001-2015 David Capello
// Copyright (C) 2001-2017 David Capello
//
// This program is distributed under the terms of
// the End-User License Agreement for Aseprite.
@ -16,16 +16,12 @@ namespace app {
// A group of tools.
class ToolGroup {
public:
ToolGroup(const char* name,
const char* label) : m_name(name)
, m_label(label) { }
ToolGroup(const char* id) : m_id(id) { }
const std::string& getName() const { return m_name; }
const std::string& getLabel() const { return m_label; }
const std::string& id() const { return m_id; }
private:
std::string m_name;
std::string m_label;
std::string m_id;
};
} // namespace tools

View File

@ -34,7 +34,8 @@ using namespace ui;
// static
Params AppMenuItem::s_contextParams;
AppMenuItem::AppMenuItem(const char* text, Command* command, const Params& params)
AppMenuItem::AppMenuItem(const std::string& text,
Command* command, const Params& params)
: MenuItem(text)
, m_key(nullptr)
, m_command(command)

View File

@ -34,7 +34,9 @@ namespace app {
app::KeyContext keyContext = app::KeyContext::Any;
};
AppMenuItem(const char* text, Command* command = nullptr, const Params& params = Params());
AppMenuItem(const std::string& text,
Command* command = nullptr,
const Params& params = Params());
~AppMenuItem();
Key* key() { return m_key; }

View File

@ -89,7 +89,7 @@ Widget* WidgetLoader::loadWidgetFromXmlFile(
ui::Widget* widget)
{
m_tooltipManager = NULL;
m_stringIdPrefix = widgetId;
m_xmlTranslator.setStringIdPrefix(widgetId.c_str());
XmlDocumentRef doc(open_xml(xmlFilename));
TiXmlHandle handle(doc.get());
@ -362,7 +362,7 @@ Widget* WidgetLoader::convertXmlElementToWidget(const TiXmlElement* elem, Widget
(middle ? MIDDLE: (bottom ? BOTTOM: TOP));
if (!widget) {
widget = new Separator(textAttr(elem, "text"), align);
widget = new Separator(m_xmlTranslator(elem, "text"), align);
}
else
widget->setAlign(widget->align() | align);
@ -397,7 +397,7 @@ Widget* WidgetLoader::convertXmlElementToWidget(const TiXmlElement* elem, Widget
if (desktop)
widget = new Window(Window::DesktopWindow);
else if (elem->Attribute("text"))
widget = new Window(Window::WithTitleBar, textAttr(elem, "text"));
widget = new Window(Window::WithTitleBar, m_xmlTranslator(elem, "text"));
else
widget = new Window(Window::WithoutTitleBar);
}
@ -419,7 +419,7 @@ Widget* WidgetLoader::convertXmlElementToWidget(const TiXmlElement* elem, Widget
}
else if (elem_name == "dropdownbutton") {
if (!widget) {
widget = new DropDownButton(textAttr(elem, "text").c_str());
widget = new DropDownButton(m_xmlTranslator(elem, "text").c_str());
}
}
else if (elem_name == "buttonset") {
@ -453,7 +453,7 @@ Widget* WidgetLoader::convertXmlElementToWidget(const TiXmlElement* elem, Widget
}
if (text)
item->setText(textAttr(elem, "text"));
item->setText(m_xmlTranslator(elem, "text"));
buttonset->addItem(item, hspan, vspan);
fillWidgetWithXmlElementAttributes(elem, root, item);
@ -527,7 +527,7 @@ void WidgetLoader::fillWidgetWithXmlElementAttributes(const TiXmlElement* elem,
widget->setId(id);
if (elem->Attribute("text"))
widget->setText(textAttr(elem, "text"));
widget->setText(m_xmlTranslator(elem, "text"));
if (elem->Attribute("tooltip") && root) {
if (!m_tooltipManager) {
@ -543,7 +543,7 @@ void WidgetLoader::fillWidgetWithXmlElementAttributes(const TiXmlElement* elem,
else if (strcmp(tooltip_dir, "right") == 0) dir = RIGHT;
}
m_tooltipManager->addTooltipFor(widget, textAttr(elem, "tooltip"), dir);
m_tooltipManager->addTooltipFor(widget, m_xmlTranslator(elem, "tooltip"), dir);
}
if (selected)
@ -723,19 +723,4 @@ static int int_attr(const TiXmlElement* elem, const char* attribute_name, int de
return (value ? strtol(value, NULL, 10): default_value);
}
std::string WidgetLoader::textAttr(const TiXmlElement* elem, const char* attrName)
{
const char* value = elem->Attribute(attrName);
if (!value)
return std::string();
else if (value[0] == '@') {
if (value[1] == '.')
return Strings::instance()->translate((m_stringIdPrefix + (value+1)).c_str());
else
return Strings::instance()->translate(value+1);
}
else
return std::string(value);
}
} // namespace app

View File

@ -1,5 +1,5 @@
// Aseprite
// Copyright (C) 2001-2016 David Capello
// Copyright (C) 2001-2017 David Capello
//
// This program is distributed under the terms of
// the End-User License Agreement for Aseprite.
@ -8,6 +8,7 @@
#define APP_WIDGET_LOADER_H_INCLUDED
#pragma once
#include "app/i18n/xml_translator.h"
#include "app/widget_type_mismatch.h"
#include <map>
@ -64,13 +65,12 @@ namespace app {
ui::Widget* convertXmlElementToWidget(const TiXmlElement* elem, ui::Widget* root, ui::Widget* parent, ui::Widget* widget);
void fillWidgetWithXmlElementAttributes(const TiXmlElement* elem, ui::Widget* root, ui::Widget* widget);
void fillWidgetWithXmlElementAttributesWithChildren(const TiXmlElement* elem, ui::Widget* root, ui::Widget* widget);
std::string textAttr(const TiXmlElement* elem, const char* attrName);
typedef std::map<std::string, IWidgetTypeCreator*> TypeCreatorsMap;
TypeCreatorsMap m_typeCreators;
ui::TooltipManager* m_tooltipManager;
std::string m_stringIdPrefix;
XmlTranslator m_xmlTranslator;
};
} // namespace app

View File

@ -1,5 +1,5 @@
// Aseprite Code Generator
// Copyright (c) 2016 David Capello
// Copyright (c) 2016-2017 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
@ -41,15 +41,15 @@ static std::string find_first_id(TiXmlElement* elem)
return "";
}
static void collect_widgets_with_strings(TiXmlElement* elem, XmlElements& widgets)
static void collect_elements_with_strings(TiXmlElement* elem, XmlElements& elems)
{
TiXmlElement* child = elem->FirstChildElement();
while (child) {
const char* text = child->Attribute("text");
const char* tooltip = child->Attribute("tooltip");
if (text || tooltip)
widgets.push_back(child);
collect_widgets_with_strings(child, widgets);
elems.push_back(child);
collect_elements_with_strings(child, elems);
child = child->NextSiblingElement();
}
}
@ -117,7 +117,7 @@ public:
m_prefixId = find_first_id(doc->RootElement());
collect_widgets_with_strings(doc->RootElement(), widgets);
collect_elements_with_strings(doc->RootElement(), widgets);
for (TiXmlElement* elem : widgets) {
checkString(elem, elem->Attribute("text"));
checkString(elem, elem->Attribute("tooltip"));
@ -125,6 +125,56 @@ public:
}
}
void checkStringsOnGuiFile(const std::string& fullFn) {
base::FileHandle inputFile(base::open_file(fullFn, "rb"));
base::UniquePtr<TiXmlDocument> doc(new TiXmlDocument());
doc->SetValue(fullFn.c_str());
if (!doc->LoadFile(inputFile.get())) {
std::cerr << doc->Value() << ":"
<< doc->ErrorRow() << ":"
<< doc->ErrorCol() << ": "
<< "error " << doc->ErrorId() << ": "
<< doc->ErrorDesc() << "\n";
throw std::runtime_error("invalid input file");
}
TiXmlHandle handle(doc);
// For each menu
TiXmlElement* xmlMenu = handle
.FirstChild("gui")
.FirstChild("menus")
.FirstChild("menu").ToElement();
while (xmlMenu) {
const char* menuId = xmlMenu->Attribute("id");
if (menuId) {
m_prefixId = menuId;
XmlElements menus;
collect_elements_with_strings(xmlMenu, menus);
for (TiXmlElement* elem : menus)
checkString(elem, elem->Attribute("text"));
}
xmlMenu = xmlMenu->NextSiblingElement();
}
// For each tool
m_prefixId = "tools";
TiXmlElement* xmlGroup = handle
.FirstChild("gui")
.FirstChild("tools")
.FirstChild("group").ToElement();
while (xmlGroup) {
XmlElements tools;
collect_elements_with_strings(xmlGroup, tools);
for (TiXmlElement* elem : tools) {
checkString(elem, elem->Attribute("text"));
checkString(elem, elem->Attribute("tooltip"));
}
xmlGroup = xmlGroup->NextSiblingElement();
}
}
void checkString(TiXmlElement* elem, const char* text) {
if (!text)
return; // Do nothing
@ -172,9 +222,11 @@ private:
};
void check_strings(const std::string& widgetsDir,
const std::string& stringsDir)
const std::string& stringsDir,
const std::string& guiFile)
{
CheckStrings cs;
cs.loadStrings(stringsDir);
cs.checkStringsOnWidgets(widgetsDir);
cs.checkStringsOnGuiFile(guiFile);
}

View File

@ -1,5 +1,5 @@
// Aseprite Code Generator
// Copyright (c) 2016 David Capello
// Copyright (c) 2016-2017 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
@ -11,6 +11,7 @@
#include <string>
void check_strings(const std::string& widgetsDir,
const std::string& stringsDir);
const std::string& stringsDir,
const std::string& guiFile);
#endif

View File

@ -31,6 +31,7 @@ static void run(int argc, const char* argv[])
PO::Option& strings = po.add("strings");
PO::Option& widgetsDir = po.add("widgets-dir").requiresValue("<dir>");
PO::Option& stringsDir = po.add("strings-dir").requiresValue("<dir>");
PO::Option& guiFile = po.add("gui-file").requiresValue("<filename>");
po.parse(argc, argv);
// Try to load the XML file
@ -75,7 +76,8 @@ static void run(int argc, const char* argv[])
else if (po.enabled(widgetsDir) &&
po.enabled(stringsDir)) {
check_strings(po.value_of(widgetsDir),
po.value_of(stringsDir));
po.value_of(stringsDir),
po.value_of(guiFile));
}
}