Merge branch 'i18n'

This commit is contained in:
David Capello 2017-10-17 18:04:26 -03:00
commit c019661bc0
51 changed files with 1097 additions and 596 deletions

3
.gitmodules vendored
View File

@ -57,3 +57,6 @@
[submodule "third_party/giflib"]
path = third_party/giflib
url = https://github.com/aseprite/giflib.git
[submodule "third_party/fmt"]
path = third_party/fmt
url = https://github.com/aseprite/fmt.git

File diff suppressed because it is too large Load Diff

View File

@ -6,6 +6,137 @@ title = Warning - Important
description = You are going to enter in "Advanced Mode".
dont_show_again = Don't show this again
[alerts]
applying_filter = FX<<Applying effect...||&Cancel
auto_remap = <<<END
Automatic Remap
<<The remap operation cannot be perfectly done for more than 256 colors.
<<Do you want to continue anyway?
||&OK||&Cancel"
END
cannot_delete_all_layers = Error<<You cannot delete all layers.||&OK
cannot_file_overwrite_on_export = <<<END
Overwrite Warning
<<You cannot Export with the same name (overwrite the original file).
<<Use File > Save As menu option in that case.
||&OK
END
cannot_open_file = Problem<<Cannot open file:<<{0}||&OK
cannot_open_folder = Problem<<Cannot open folder:<<{0}||&OK
cannot_save_in_read_only_file = Problem<<The selected file is read-only. Try with other file.||&Go back
clipboard_access_locked = Error<<Cannot access to the clipboard.<<Maybe other application is using it.||&OK
clipboard_image_format_not_supported = Error<<The current clipboard image format is not supported.||&OK
delete_selected_backups = <<<END
Warning
<<Do you really want to delete the selected {0} backup(s)?
||&Yes||&No
END
delete_shortcut = <<<END
Warning
<<Do you really want to delete '{0}' keyboard shortcut?
||&Yes||&No
END
empty_rect_importing_sprite_sheet = <<<END
Import Sprite Sheet
<<The specified rectangle does not create any tile.
<<Select a rectangle inside the sprite region.
||&OK
END
error_loading_file = Error<<Error loading file: {0}||&OK
error_saving_file = Error<<Error saving file: {0}||&OK
export_animation_in_sequence = <<<END
Notice
<<Do you want to export the animation in {0} files?
<<{1}, {2}...
||&Agree||&Cancel
END
file_format_doesnt_support_error = <<<END
Error
<<File format ".{0}" doesn't support:
{1}
<<You must select other format.
<<Use ".ase" to keep all the sprite information.
||&OK
END
file_format_doesnt_support_warning = <<<END
Warning
<<File format ".{0}" doesn't support:
{1}
<<You can use ".ase" format to keep all this information.
<<Do you want continue with ".{0}" anyway?
||&Yes||&No
END
file_format_alpha_channel = Alpha channel
file_format_frame_tags = Frame tags
file_format_frames = Frames
file_format_grayscale_mode = Grayscale mode
file_format_indexed_mode = Indexed mode
file_format_layers = Layers
file_format_palette_changes = Palette changes between frames
file_format_rgb_mode = RGB mode
invalid_chars_in_filename = <<<END
Error
<<The file name cannot contain the following character(s):
<< {0}
||&OK
END
invalid_fg_or_bg_colors = <<<END
Aseprite
<<The current selected foreground and/or background color
<<is out of range. Select a valid color in the palette.
||&OK
END
job_working = {0}<<Working...||&Cancel
nothing_to_report = Crash Report<<Nothing to report||&OK
uninstall_extension_warning = <<<END
Warning
<<Do you really want to uninstall '{0}' extension?
||&Yes||&No
END
update_screen_ui_scaling_with_theme_values = <<<END
Update Screen/UI Scaling
<<The new theme '{0}' wants to adjust some values for you:
<< Screen Scaling: {1}% -> {2}%
<< UI Scaling: {3}% -> {4}%
<<Allow these changes?
||&Adjust Scaling||&Don't Adjust Scaling
END
update_extension = <<<END
Update Extension
<<The extension '{0}' already exists.
<<Do you want to {1} from v{2} to v{3}?
||&Yes||&No
END
update_extension_downgrade = downgrade
update_extension_upgrade = upgrade
restart_by_preferences = <<<END
Aseprite
<<You must restart the program to see your changes to:{0}
||&OK
END
restart_by_preferences_save_recovery_data_period = Automatically save recovery data every X minutes
restore_all_shortcuts = <<<END
Warning
<<Do you want to restore all keyboard shortcuts
<<to their original default settings?
||&Yes||&No
END
save_sprite_changes = <<<END
Warning
<<Saving changes to the sprite
<<"{0}" before {1}?
||&Save||Do&n't Save||&Cancel
END
save_sprite_changes_quitting = quitting
save_sprite_changes_closing = closing
overwrite_existent_file = Warning<<File exists, overwrite it?<<{0}||&Yes||&No||&Cancel
overwrite_files_on_export_sprite_sheet = <<<END
Export Sprite Sheet Warning
<<Do you want to overwrite the following file(s)?
{0}
||&Yes||&No
END
[brush_slot_params]
brush = Brush:
brush_type = Type
@ -22,6 +153,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 +331,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 +357,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 +742,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 +802,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 +856,9 @@ percentage = Percentage:
interpolation = Interpolation:
method = Method:
[tab_popup_menu]
close = &Close
[timeline_conf]
position = Position:
left = &Left
@ -556,6 +887,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

@ -230,6 +230,34 @@ be used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization of the copyright holder.
```
# [fmt](https://github.com/fmtlib/fmt)
```
Copyright (c) 2012 - 2016, Victor Zverovich
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
```
# [FreeType](http://www.freetype.org/)
```

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
@ -554,7 +555,8 @@ target_link_libraries(app-lib
${FREETYPE_LIBRARIES}
${HARFBUZZ_LIBRARIES}
json11
archive_static)
archive_static
fmt)
if(ENABLE_SCRIPTING)
target_link_libraries(app-lib script-lib)

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

@ -16,6 +16,7 @@
#include "app/document_exporter.h"
#include "app/file/file.h"
#include "app/file_selector.h"
#include "app/i18n/strings.h"
#include "app/modules/editors.h"
#include "app/pref/preferences.h"
#include "app/restore_visible_layers.h"
@ -29,6 +30,7 @@
#include "base/string.h"
#include "doc/frame_tag.h"
#include "doc/layer.h"
#include "fmt/format.h"
#include "export_sprite_sheet.xml.h"
@ -138,7 +140,6 @@ namespace {
!dataname.empty() &&
base::is_file(dataname))) {
std::stringstream text;
text << "Export Sprite Sheet Warning<<Do you want to overwrite the following file(s)?";
if (base::is_file(filename))
text << "<<" << base::get_file_name(filename).c_str();
@ -146,8 +147,9 @@ namespace {
if (base::is_file(dataname))
text << "<<" << base::get_file_name(dataname).c_str();
text << "||&Yes||&No";
if (Alert::show(text.str().c_str()) != 1)
if (ui::Alert::show(
fmt::format(Strings::alerts_overwrite_files_on_export_sprite_sheet(),
text.str())) != 1)
return false;
}
return true;

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.
@ -16,6 +16,7 @@
#include "app/context_access.h"
#include "app/document_access.h"
#include "app/document_api.h"
#include "app/i18n/strings.h"
#include "app/modules/editors.h"
#include "app/modules/gui.h"
#include "app/modules/palettes.h"
@ -379,10 +380,7 @@ void ImportSpriteSheetCommand::onExecute(Context* context)
}
if (animation.size() == 0) {
Alert::show("Import Sprite Sheet"
"<<The specified rectangle does not create any tile."
"<<Select a rectangle inside the sprite region."
"||&OK");
Alert::show(Strings::alerts_empty_rect_importing_sprite_sheet());
return;
}

View File

@ -13,6 +13,7 @@
#include "app/commands/command.h"
#include "app/context.h"
#include "app/file_selector.h"
#include "app/i18n/strings.h"
#include "app/match_words.h"
#include "app/resource_finder.h"
#include "app/tools/tool.h"
@ -28,6 +29,7 @@
#include "base/scoped_value.h"
#include "base/split_string.h"
#include "base/string.h"
#include "fmt/format.h"
#include "ui/graphics.h"
#include "ui/listitem.h"
#include "ui/paint_event.h"
@ -144,11 +146,10 @@ private:
// Key::disableAccel() will modify the accels() collection itself.
ui::Accelerator accel = m_key->accels()[index];
if (Alert::show(
"Warning"
"<<Do you really want to delete '%s' keyboard shortcut?"
"||&Yes||&No",
accel.toString().c_str()) != 1)
if (ui::Alert::show(
fmt::format(
Strings::alerts_delete_shortcut(),
accel.toString())) != 1)
return;
m_key->disableAccel(accel);
@ -586,10 +587,7 @@ private:
}
void onReset() {
if (Alert::show("Warning"
"<<Do you want to restore all keyboard shortcuts"
"<<to their original default settings?"
"||&Yes||&No") == 1) {
if (ui::Alert::show(Strings::alerts_restore_all_shortcuts()) == 1) {
app::KeyboardShortcuts::instance()->reset();
layout();
}

View File

@ -13,11 +13,13 @@
#include "app/commands/params.h"
#include "app/context_access.h"
#include "app/file_selector.h"
#include "app/i18n/strings.h"
#include "app/modules/gui.h"
#include "app/transaction.h"
#include "app/util/msk_file.h"
#include "doc/mask.h"
#include "doc/sprite.h"
#include "fmt/format.h"
#include "ui/alert.h"
namespace app {
@ -68,9 +70,10 @@ void LoadMaskCommand::onExecute(Context* context)
}
base::UniquePtr<Mask> mask(load_msk_file(m_filename.c_str()));
if (!mask)
throw base::Exception("Error loading .msk file: %s",
static_cast<const char*>(m_filename.c_str()));
if (!mask) {
ui::Alert::show(fmt::format(Strings::alerts_error_loading_file(), m_filename));
return;
}
{
ContextWriter writer(reader);

View File

@ -14,10 +14,12 @@
#include "app/context.h"
#include "app/file/palette_file.h"
#include "app/file_selector.h"
#include "app/i18n/strings.h"
#include "app/modules/palettes.h"
#include "base/fs.h"
#include "base/unique_ptr.h"
#include "doc/palette.h"
#include "fmt/format.h"
#include "ui/alert.h"
namespace app {
@ -80,7 +82,7 @@ void LoadPaletteCommand::onExecute(Context* context)
base::UniquePtr<doc::Palette> palette(load_palette(filename.c_str()));
if (!palette) {
if (context->isUIAvailable())
Alert::show("Error<<Loading palette file||&Close");
ui::Alert::show(fmt::format(Strings::alerts_error_loading_file(), filename));
return;
}

View File

@ -14,6 +14,7 @@
#include "app/context.h"
#include "app/extensions.h"
#include "app/file_selector.h"
#include "app/i18n/strings.h"
#include "app/ini_file.h"
#include "app/launcher.h"
#include "app/pref/preferences.h"
@ -28,6 +29,7 @@
#include "base/string.h"
#include "base/version.h"
#include "doc/image.h"
#include "fmt/format.h"
#include "render/render.h"
#include "she/display.h"
#include "she/system.h"
@ -371,7 +373,7 @@ public:
m_pref.general.dataRecovery(enableDataRecovery()->isSelected());
m_pref.general.dataRecoveryPeriod(newPeriod);
warnings += "<<- Automatically save recovery data every";
warnings += "<<- " + Strings::alerts_restart_by_preferences_save_recovery_data_period();
}
m_pref.editor.zoomFromCenterWithWheel(zoomFromCenterWithWheel()->isSelected());
@ -463,9 +465,9 @@ public:
m_pref.save();
if (!warnings.empty()) {
ui::Alert::show(PACKAGE
"<<You must restart the program to see your changes to:%s"
"||&OK", warnings.c_str());
ui::Alert::show(
fmt::format(Strings::alerts_restart_by_preferences(),
warnings));
}
if (reset_screen)
@ -778,17 +780,13 @@ private:
// Ask if the user want to adjust the Screen/UI Scaling
const int result =
ui::Alert::show(
"Update Screen/UI Scaling"
"<<The new theme '%s' wants to adjust some values for you:"
"<< Screen Scaling: %d%% -> %d%%"
"<< UI Scaling: %d%% -> %d%%"
"<<Allow these changes?"
"||&Adjust Scaling||&Don't Adjust Scaling",
themeName.c_str(),
fmt::format(
Strings::alerts_update_screen_ui_scaling_with_theme_values(),
themeName,
100 * m_pref.general.screenScale(),
100 * (newScreenScale > 0 ? newScreenScale: m_pref.general.screenScale()),
100 * m_pref.general.uiScale(),
100 * (newUIScale > 0 ? newUIScale: m_pref.general.uiScale()));
100 * (newUIScale > 0 ? newUIScale: m_pref.general.uiScale())));
if (result == 1) {
// Preferred UI Scaling factor
@ -865,14 +863,13 @@ private:
// Uninstall?
if (ui::Alert::show(
"Update Extension"
"<<The extension '%s' already exists."
"<<Do you want to %s from v%s to v%s?"
"||&Yes||&No",
ext->name().c_str(),
(isDowngrade ? "downgrade": "upgrade"),
ext->version().c_str(),
info.version.c_str()) != 1)
fmt::format(
Strings::alerts_update_extension(),
ext->name(),
(isDowngrade ? Strings::alerts_update_extension_downgrade():
Strings::alerts_update_extension_upgrade()),
ext->version(),
info.version)) != 1)
return;
// Uninstall old version
@ -917,10 +914,9 @@ private:
return;
if (ui::Alert::show(
"Warning"
"<<Do you really want to uninstall '%s' extension?"
"||&Yes||&No",
item->text().c_str()) != 1)
fmt::format(
Strings::alerts_uninstall_extension_warning(),
item->text())) != 1)
return;
try {

View File

@ -195,9 +195,7 @@ void PasteTextCommand::onExecute(Context* ctx)
}
}
catch (const std::exception& ex) {
ui::Alert::show(PACKAGE
"<<%s"
"||&OK", ex.what());
Console::showException(ex);
}
}

View File

@ -12,9 +12,10 @@
#include "app/commands/command.h"
#include "app/context_access.h"
#include "app/document_api.h"
#include "app/i18n/strings.h"
#include "app/modules/gui.h"
#include "app/ui/status_bar.h"
#include "app/transaction.h"
#include "app/ui/status_bar.h"
#include "doc/layer.h"
#include "doc/sprite.h"
#include "ui/alert.h"
@ -69,7 +70,7 @@ void RemoveLayerCommand::onExecute(Context* context)
}
if (deletedTopLevelLayers == sprite->root()->layersCount()) {
ui::Alert::show("Error<<You cannot delete all layers.||&OK");
ui::Alert::show(Strings::alerts_cannot_delete_all_layers());
return;
}
@ -79,7 +80,7 @@ void RemoveLayerCommand::onExecute(Context* context)
}
else {
if (sprite->allLayersCount() == 1) {
ui::Alert::show("Error<<You cannot delete the last layer.||&OK");
ui::Alert::show(Strings::alerts_cannot_delete_all_layers());
return;
}

View File

@ -18,6 +18,7 @@
#include "app/context_access.h"
#include "app/file/file.h"
#include "app/file_selector.h"
#include "app/i18n/strings.h"
#include "app/job.h"
#include "app/modules/gui.h"
#include "app/pref/preferences.h"
@ -207,10 +208,7 @@ bool SaveFileBaseCommand::saveAsDialog(
if (!forbiddenFilename.empty() &&
base::normalize_path(forbiddenFilename) ==
base::normalize_path(filename)) {
ui::Alert::show("Overwrite Warning"
"<<You cannot save a copy with the same name (overwrite the original file)."
"<<Use File > Save menu option in that case."
"||&OK");
ui::Alert::show(Strings::alerts_cannot_file_overwrite_on_export());
goto again;
}

View File

@ -11,10 +11,12 @@
#include "app/commands/command.h"
#include "app/context_access.h"
#include "app/file_selector.h"
#include "app/i18n/strings.h"
#include "app/util/msk_file.h"
#include "base/fs.h"
#include "doc/mask.h"
#include "doc/sprite.h"
#include "fmt/format.h"
#include "ui/alert.h"
namespace app {
@ -55,7 +57,7 @@ void SaveMaskCommand::onExecute(Context* context)
std::string filename = selFilename.front();
if (save_msk_file(document->mask(), filename.c_str()) != 0)
ui::Alert::show("Error<<Error saving .msk file<<%s||&Close", filename.c_str());
ui::Alert::show(fmt::format(Strings::alerts_error_saving_file(), filename));
}
Command* CommandFactory::createSaveMaskCommand()

View File

@ -14,9 +14,11 @@
#include "app/context.h"
#include "app/file/palette_file.h"
#include "app/file_selector.h"
#include "app/i18n/strings.h"
#include "app/modules/palettes.h"
#include "base/fs.h"
#include "doc/palette.h"
#include "fmt/format.h"
#include "ui/alert.h"
namespace app {
@ -68,7 +70,7 @@ void SavePaletteCommand::onExecute(Context* context)
}
if (!save_palette(filename.c_str(), palette, 16)) // TODO 16 should be configurable
Alert::show("Error<<Saving palette file||&Close");
ui::Alert::show(fmt::format(Strings::alerts_error_saving_file(), filename));
if (m_preset == get_default_palette_preset_name()) {
set_default_palette(palette);

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.
@ -11,6 +11,7 @@
#include "app/app.h"
#include "app/commands/filters/filter_manager_impl.h"
#include "app/console.h"
#include "app/i18n/strings.h"
#include "app/ini_file.h"
#include "app/modules/editors.h"
#include "app/modules/gui.h"
@ -77,8 +78,7 @@ FilterWorker::FilterWorker(FilterManagerImpl* filterMgr)
m_cancelled = false;
m_abort = false;
m_alertWindow = ui::Alert::create(PACKAGE
"<<Applying effect...||&Cancel");
m_alertWindow = ui::Alert::create(Strings::alerts_applying_filter());
m_alertWindow->addProgress();
m_timer.Tick.connect(&FilterWorker::onMonitoringTick, this);

View File

@ -20,6 +20,7 @@
#include "base/fs.h"
#include "doc/doc.h"
#include "fixmath/fixmath.h"
#include "fmt/format.h"
#include "ui/alert.h"
#include "zlib.h"
@ -403,14 +404,17 @@ bool AseFormat::onPostLoad(FileOp* fop)
if (flat && ase_has_groups(group)) {
if (fop->context() &&
fop->context()->isUIAvailable() &&
ui::Alert::show("Warning"
"<<The selected file \"%s\" has layer groups."
"<<Do you want to open it with \"%s %s\" anyway?"
ui::Alert::show(
fmt::format(
// This message is not translated because is used only in the old v1.1 only
"Warning"
"<<The selected file \"{0}\" has layer groups."
"<<Do you want to open it with \"{1} {2}\" anyway?"
"<<"
"<<Note: Layers inside groups will be converted to top level layers."
"||&Yes||&No",
base::get_file_name(fop->filename()).c_str(),
PACKAGE, ver.c_str()) != 1) {
base::get_file_name(fop->filename()),
PACKAGE, ver)) != 1) {
return false;
}
ase_ungroup_all(group);

View File

@ -19,6 +19,7 @@
#include "app/file/format_options.h"
#include "app/file/split_filename.h"
#include "app/filename_formatter.h"
#include "app/i18n/strings.h"
#include "app/modules/gui.h"
#include "app/modules/palettes.h"
#include "app/ui/status_bar.h"
@ -29,6 +30,7 @@
#include "base/string.h"
#include "dio/detect_format.h"
#include "doc/doc.h"
#include "fmt/format.h"
#include "render/quantization.h"
#include "render/render.h"
#include "ui/alert.h"
@ -327,6 +329,13 @@ FileOp* FileOp::createSaveDocumentOperation(const Context* context,
// Get the extension of the filename (in lower case)
LOG("FILE: Saving document \"%s\"\n", filename.c_str());
// Check for read-only attribute
if (base::has_readonly_attr(filename)) {
fop->setError("Error saving \"%s\" file, it's read-only",
filename.c_str());
return fop.release();
}
// Get the format through the extension of the filename
fop->m_format = FileFormatsManager::instance()->getFileFormat(
dio::detect_format_by_file_extension(filename));
@ -347,32 +356,32 @@ FileOp* FileOp::createSaveDocumentOperation(const Context* context,
case IMAGE_RGB:
if (!(fop->m_format->support(FILE_SUPPORT_RGB))) {
warnings += "<<- RGB format";
warnings += "<<- " + Strings::alerts_file_format_rgb_mode();
fatal = true;
}
if (!(fop->m_format->support(FILE_SUPPORT_RGBA)) &&
fop->m_document->sprite()->needAlpha()) {
warnings += "<<- Alpha channel";
warnings += "<<- " + Strings::alerts_file_format_alpha_channel();
}
break;
case IMAGE_GRAYSCALE:
if (!(fop->m_format->support(FILE_SUPPORT_GRAY))) {
warnings += "<<- Grayscale format";
warnings += "<<- " + Strings::alerts_file_format_grayscale_mode();
fatal = true;
}
if (!(fop->m_format->support(FILE_SUPPORT_GRAYA)) &&
fop->m_document->sprite()->needAlpha()) {
warnings += "<<- Alpha channel";
warnings += "<<- " + Strings::alerts_file_format_alpha_channel();
}
break;
case IMAGE_INDEXED:
if (!(fop->m_format->support(FILE_SUPPORT_INDEXED))) {
warnings += "<<- Indexed format";
warnings += "<<- " + Strings::alerts_file_format_indexed_mode();
fatal = true;
}
break;
@ -382,14 +391,14 @@ FileOp* FileOp::createSaveDocumentOperation(const Context* context,
if (fop->m_roi.frames() > 1) {
if (!fop->m_format->support(FILE_SUPPORT_FRAMES) &&
!fop->m_format->support(FILE_SUPPORT_SEQUENCES)) {
warnings += "<<- Frames";
warnings += "<<- " + Strings::alerts_file_format_frames();
}
}
// Layers support
if (fop->m_document->sprite()->root()->layersCount() > 1) {
if (!(fop->m_format->support(FILE_SUPPORT_LAYERS))) {
warnings += "<<- Layers";
warnings += "<<- " + Strings::alerts_file_format_layers();
}
}
@ -397,14 +406,14 @@ FileOp* FileOp::createSaveDocumentOperation(const Context* context,
if (fop->m_document->sprite()->getPalettes().size() > 1) {
if (!fop->m_format->support(FILE_SUPPORT_PALETTES) &&
!fop->m_format->support(FILE_SUPPORT_SEQUENCES)) {
warnings += "<<- Palette changes between frames";
warnings += "<<- " + Strings::alerts_file_format_palette_changes();
}
}
// Check frames support
if (!fop->m_document->sprite()->frameTags().empty()) {
if (!fop->m_format->support(FILE_SUPPORT_FRAME_TAGS)) {
warnings += "<<- Frame tags";
warnings += "<<- " + Strings::alerts_file_format_frame_tags();
}
}
@ -438,26 +447,12 @@ FileOp* FileOp::createSaveDocumentOperation(const Context* context,
if (!warnings.empty()) {
// Interative
if (context && context->isUIAvailable()) {
warnings += "<<You can use \".ase\" format to keep all this information.";
std::string title, buttons;
if (fatal) {
title = "Error";
buttons = "&Close";
}
else {
title = "Warning";
buttons = "&Yes||&No";
}
int ret = ui::Alert::show("%s<<File format \".%s\" doesn't support:%s"
"<<Do you want continue with \".%s\" anyway?"
"||%s",
title.c_str(),
int ret = ui::Alert::show(
fmt::format(
(fatal ? Strings::alerts_file_format_doesnt_support_error():
Strings::alerts_file_format_doesnt_support_warning()),
fop->m_format->name(),
warnings.c_str(),
fop->m_format->name(),
buttons.c_str());
warnings));
// Operation can't be done (by fatal error) or the user cancel
// the operation
@ -510,13 +505,12 @@ FileOp* FileOp::createSaveDocumentOperation(const Context* context,
if (context && context->isUIAvailable() &&
fop->m_seq.filename_list.size() > 1 &&
ui::Alert::show("Notice"
"<<Do you want to export the animation in %d files?"
"<<%s, %s..."
"||&Agree||&Cancel",
ui::Alert::show(
fmt::format(
Strings::alerts_export_animation_in_sequence(),
int(fop->m_seq.filename_list.size()),
base::get_file_name(fop->m_seq.filename_list[0]).c_str(),
base::get_file_name(fop->m_seq.filename_list[1]).c_str()) != 1) {
base::get_file_name(fop->m_seq.filename_list[0]),
base::get_file_name(fop->m_seq.filename_list[1]))) != 1) {
return nullptr;
}
}

View File

@ -1,5 +1,5 @@
// Aseprite
// Copyright (C) 2016 David Capello
// Copyright (C) 2016, 2017 David Capello
//
// This program is distributed under the terms of
// the End-User License Agreement for Aseprite.
@ -61,7 +61,7 @@ Strings::Strings()
}
}
const std::string& Strings::translate(const char* id)
const std::string& Strings::translate(const char* id) const
{
auto it = m_strings.find(id);
if (it != m_strings.end())

View File

@ -1,5 +1,5 @@
// Aseprite
// Copyright (C) 2016 David Capello
// Copyright (C) 2016-2017 David Capello
//
// This program is distributed under the terms of
// the End-User License Agreement for Aseprite.
@ -16,21 +16,19 @@
namespace app {
// Singleton class to load and access "strings/english.txt" file.
class Strings {
// Singleton class to load and access "strings/en.ini" file.
class Strings : public app::gen::Strings<app::Strings> {
public:
static Strings* instance();
const std::string& translate(const char* id);
const std::string& translate(const char* id) const;
private:
Strings();
std::unordered_map<std::string, std::string> m_strings;
mutable std::unordered_map<std::string, std::string> m_strings;
};
#define tr(id) (Strings::instance()->translate(id))
} // namespace app
#endif

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

@ -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.
@ -12,9 +12,11 @@
#include "app/app.h"
#include "app/console.h"
#include "app/i18n/strings.h"
#include "base/mutex.h"
#include "base/scoped_lock.h"
#include "base/thread.h"
#include "fmt/format.h"
#include "ui/alert.h"
#include "ui/widget.h"
#include "ui/window.h"
@ -43,7 +45,8 @@ Job::Job(const char* jobName)
m_mutex = new base::mutex();
if (App::instance()->isGui()) {
m_alert_window = ui::Alert::create("%s<<Working...||&Cancel", jobName);
m_alert_window = ui::Alert::create(
fmt::format(Strings::alerts_job_working(), jobName));
m_alert_window->addProgress();
m_timer.reset(new ui::Timer(kMonitoringPeriod, m_alert_window.get()));

View File

@ -1,5 +1,5 @@
// Aseprite
// Copyright (C) 2001-2015 David Capello
// Copyright (C) 2001-2015, 2017 David Capello
//
// This program is distributed under the terms of
// the End-User License Agreement for Aseprite.
@ -10,8 +10,10 @@
#include "app/launcher.h"
#include "app/i18n/strings.h"
#include "base/exception.h"
#include "base/launcher.h"
#include "fmt/format.h"
#include "ui/alert.h"
namespace app {
@ -25,13 +27,13 @@ void open_url(const std::string& url)
void open_file(const std::string& file)
{
if (!base::launcher::open_file(file))
ui::Alert::show("Problem<<Cannot open file:<<%s||&Close", file.c_str());
ui::Alert::show(fmt::format(Strings::alerts_cannot_open_file(), file));
}
void open_folder(const std::string& file)
{
if (!base::launcher::open_folder(file))
ui::Alert::show("Problem<<Cannot open folder:<<%s||&Close", file.c_str());
ui::Alert::show(fmt::format(Strings::alerts_cannot_open_folder(), file));
}
} // namespace launcher

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.
@ -11,6 +11,8 @@
#include "app/send_crash.h"
#include "app/app.h"
#include "app/console.h"
#include "app/i18n/strings.h"
#include "app/resource_finder.h"
#include "base/bind.h"
#include "base/fs.h"
@ -56,7 +58,7 @@ std::string SendCrash::notificationText()
void SendCrash::notificationClick()
{
if (m_dumpFilename.empty()) {
ui::Alert::show("Crash Report<<Nothing to report||&OK");
ui::Alert::show(Strings::alerts_nothing_to_report());
return;
}
@ -83,7 +85,7 @@ void SendCrash::notificationClick()
m_dumpFilename = "";
}
catch (const std::exception& ex) {
ui::Alert::show("Error<<%s||&OK", ex.what());
Console::showException(ex);
}
}
}

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

@ -28,6 +28,7 @@
#include "app/context_access.h"
#include "app/document_api.h"
#include "app/document_undo.h"
#include "app/i18n/strings.h"
#include "app/ini_file.h"
#include "app/modules/editors.h"
#include "app/modules/gui.h"
@ -599,11 +600,7 @@ void ColorBar::onRemapButtonClick()
// Check the remap
if (!remap.isFor8bit() &&
Alert::show(
"Automatic Remap"
"<<The remap operation cannot be perfectly done for more than 256 colors."
"<<Do you want to continue anyway?"
"||&OK||&Cancel") != 1) {
Alert::show(Strings::alerts_auto_remap()) != 1) {
return;
}

View File

@ -13,12 +13,14 @@
#include "app/app_menus.h"
#include "app/crash/data_recovery.h"
#include "app/crash/session.h"
#include "app/i18n/strings.h"
#include "app/modules/gui.h"
#include "app/ui/drop_down_button.h"
#include "app/ui/separator_in_view.h"
#include "app/ui/skin/skin_theme.h"
#include "app/ui/workspace.h"
#include "base/bind.h"
#include "fmt/format.h"
#include "ui/alert.h"
#include "ui/button.h"
#include "ui/entry.h"
@ -224,10 +226,9 @@ void DataRecoveryView::onDelete()
return;
// Delete one backup
if (Alert::show(PACKAGE
"<<Do you really want to delete the selected %d backup(s)?"
"||&Yes||&No",
int(items.size())) != 1)
if (Alert::show(
fmt::format(Strings::alerts_delete_selected_backups(),
int(items.size()))) != 1)
return; // Cancel
for (auto item : items) {

View File

@ -19,6 +19,7 @@
#include "app/console.h"
#include "app/context_access.h"
#include "app/document_access.h"
#include "app/i18n/strings.h"
#include "app/modules/editors.h"
#include "app/modules/palettes.h"
#include "app/pref/preferences.h"
@ -37,6 +38,7 @@
#include "doc/document_event.h"
#include "doc/layer.h"
#include "doc/sprite.h"
#include "fmt/format.h"
#include "ui/accelerator.h"
#include "ui/alert.h"
#include "ui/menu.h"
@ -278,12 +280,12 @@ bool DocumentView::onCloseView(Workspace* workspace, bool quitting)
// see if the sprite has changes
while (m_document->isModified()) {
// ask what want to do the user with the changes in the sprite
int ret = Alert::show("Warning"
"<<Saving changes to the sprite"
"<<\"%s\" before %s?"
"||&Save||Do&n't Save||&Cancel",
m_document->name().c_str(),
quitting ? "quitting": "closing");
int ret = Alert::show(
fmt::format(
Strings::alerts_save_sprite_changes(),
m_document->name(),
(quitting ? Strings::alerts_save_sprite_changes_quitting():
Strings::alerts_save_sprite_changes_closing())));
if (ret == 1) {
// "save": save the changes

View File

@ -20,6 +20,7 @@
#include "app/context.h"
#include "app/context_access.h"
#include "app/document_undo.h"
#include "app/i18n/strings.h"
#include "app/modules/gui.h"
#include "app/modules/palettes.h"
#include "app/pref/preferences.h"
@ -48,6 +49,7 @@
#include "doc/remap.h"
#include "doc/slice.h"
#include "doc/sprite.h"
#include "fmt/format.h"
#include "render/dithering.h"
#include "render/render.h"
#include "ui/ui.h"
@ -591,10 +593,7 @@ tools::ToolLoop* create_tool_loop(
app::Color bg = colorbar->getBgColor();
if (!fg.isValid() || !bg.isValid()) {
Alert::show(PACKAGE
"<<The current selected foreground and/or background color"
"<<is out of range. Select a valid color in the color-bar."
"||&Close");
Alert::show(Strings::alerts_invalid_fg_or_bg_colors());
return NULL;
}
@ -626,11 +625,7 @@ tools::ToolLoop* create_tool_loop(
saveLastPoint);
}
catch (const std::exception& ex) {
Alert::show(PACKAGE
"<<Error drawing ink:"
"<<%s"
"||&Close",
ex.what());
Console::showException(ex);
return NULL;
}
}

View File

@ -10,11 +10,10 @@
#include "app/ui/file_selector.h"
#include "base/bind.h"
#include "base/string.h"
#include "app/app.h"
#include "app/console.h"
#include "app/file/file.h"
#include "app/i18n/strings.h"
#include "app/ini_file.h"
#include "app/modules/gfx.h"
#include "app/modules/gui.h"
@ -24,10 +23,13 @@
#include "app/ui/skin/skin_theme.h"
#include "app/widget_loader.h"
#include "base/bind.h"
#include "base/bind.h"
#include "base/convert_to.h"
#include "base/fs.h"
#include "base/split_string.h"
#include "base/string.h"
#include "base/unique_ptr.h"
#include "fmt/format.h"
#include "ui/ui.h"
#include "new_folder_window.xml.h"
@ -625,13 +627,17 @@ again:
fn.find('|') != std::string::npos);
#endif
if (has_invalid_char) {
Alert::show("Error"
"<<The file name cannot contain the following character(s):"
"<< /"
const char* invalid_chars =
"/"
#ifdef _WIN32
" \\ : * ? \" < > |"
#endif
"||&OK");
;
ui::Alert::show(
fmt::format(
Strings::alerts_invalid_chars_in_filename(),
invalid_chars));
// show the window again
setVisible(true);
@ -646,8 +652,10 @@ again:
}
if (m_type == FileSelectorType::Save && base::is_file(buf)) {
int ret = Alert::show("Warning<<File exists, overwrite it?<<%s||&Yes||&No||&Cancel",
base::get_file_name(buf).c_str());
int ret = Alert::show(
fmt::format(
Strings::alerts_overwrite_existent_file(),
base::get_file_name(buf)));
if (ret == 2) {
setVisible(true);
goto again;
@ -655,8 +663,7 @@ again:
else if (ret == 1) {
// Check for read-only attribute
if (base::has_readonly_attr(buf)) {
ui::Alert::show(
"Problem<<The selected file is read-only. Try with other file.||&Go back");
ui::Alert::show(Strings::alerts_cannot_save_in_read_only_file());
setVisible(true);
goto again;

View File

@ -24,6 +24,7 @@
#include "app/ui_context.h"
#include "base/bind.h"
#include "base/exception.h"
#include "fmt/format.h"
#include "ui/label.h"
#include "ui/resize_event.h"
#include "ui/system.h"
@ -143,7 +144,7 @@ void HomeView::onCheckingUpdates()
void HomeView::onUpToDate()
{
checkUpdate()->setText(PACKAGE " is up to date");
checkUpdate()->setText(fmt::format("{0} is up to date", PACKAGE));
checkUpdate()->setVisible(true);
layout();
@ -151,7 +152,8 @@ void HomeView::onUpToDate()
void HomeView::onNewUpdate(const std::string& url, const std::string& version)
{
checkUpdate()->setText("New " PACKAGE " v" + version + " available!");
checkUpdate()->setText(fmt::format("New {0} v{1} available!",
PACKAGE, version));
checkUpdate()->setUrl(url);
checkUpdate()->setVisible(true);
checkUpdate()->InitTheme.connect(

View File

@ -3318,8 +3318,8 @@ void Timeline::dropRange(DropOp op)
moveRange(newFromRange);
}
catch (const std::exception& e) {
ui::Alert::show("Problem<<%s||&OK", e.what());
catch (const std::exception& ex) {
Console::showException(ex);
}
}

View File

@ -1,5 +1,5 @@
// Aseprite
// Copyright (C) 2016 David Capello
// Copyright (C) 2016-2017 David Capello
//
// This program is distributed under the terms of
// the End-User License Agreement for Aseprite.
@ -10,6 +10,7 @@
#include "app/util/clipboard_native.h"
#include "app/i18n/strings.h"
#include "base/serialization.h"
#include "base/unique_ptr.h"
#include "clip/clip.h"
@ -43,10 +44,10 @@ namespace {
void custom_error_handler(clip::ErrorCode code) {
switch (code) {
case clip::ErrorCode::CannotLock:
ui::Alert::show("Error<<Cannot access to the clipboard.\nMaybe other application is using it.||&OK");
ui::Alert::show(Strings::alerts_clipboard_access_locked());
break;
case clip::ErrorCode::ImageNotSupported:
ui::Alert::show("Error<<The current clipboard image format is not supported.||&OK");
ui::Alert::show(Strings::alerts_clipboard_image_format_not_supported());
break;
}
}

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));
}
}

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.
@ -54,7 +54,7 @@ void gen_strings_class(const std::string& inputFn)
for (auto key : keys) {
textId.append(key);
std::cout << " const std::string& " << to_cpp(textId) << "() const { return static_cast<T*>(this)->translate(\"" << textId << "\"); }\n";
std::cout << " static const std::string& " << to_cpp(textId) << "() { return T::instance()->translate(\"" << textId << "\"); }\n";
textId.erase(section.size()+1);
}

View File

@ -45,7 +45,6 @@
#include "ui/slider.h"
#include "ui/theme.h"
#include <cstdarg>
#include <cstdio>
namespace ui {
@ -73,13 +72,10 @@ void Alert::setProgress(double progress)
m_progress->setValue(int(MID(0.0, progress * 100.0, 100.0)));
}
AlertPtr Alert::create(const char* format, ...)
// static
AlertPtr Alert::create(const std::string& _msg)
{
// Process arguments
std::va_list ap;
va_start(ap, format);
std::string msg = base::string_vprintf(format, ap);
va_end(ap);
std::string msg(_msg);
// Create the alert window
AlertPtr window(new Alert());
@ -88,13 +84,9 @@ AlertPtr Alert::create(const char* format, ...)
}
// static
int Alert::show(const char* format, ...)
int Alert::show(const std::string& _msg)
{
// Process arguments
std::va_list ap;
va_start(ap, format);
std::string msg = base::string_vprintf(format, ap);
va_end(ap);
std::string msg(_msg);
// Create the alert window
AlertPtr window(new Alert());
@ -134,7 +126,14 @@ void Alert::processString(std::string& buf)
// Process buffer
c = 0;
beg = 0;
for (; ; c++) {
for (;;) {
// Ignore characters
if (buf[c] == '\n' ||
buf[c] == '\r') {
buf.erase(c, 1);
continue;
}
if ((!buf[c]) ||
((buf[c] == buf[c+1]) &&
((buf[c] == '<') ||
@ -185,9 +184,10 @@ void Alert::processString(std::string& buf)
case '-': separator=true; break;
case '|': button=true; break;
}
c++;
++c;
}
}
++c;
}
auto box1 = new Box(VERTICAL);

View File

@ -1,5 +1,5 @@
// Aseprite UI Library
// Copyright (C) 2001-2016 David Capello
// Copyright (C) 2001-2017 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
@ -31,8 +31,8 @@ namespace ui {
int show();
static AlertPtr create(const char* format, ...);
static int show(const char* format, ...);
static AlertPtr create(const std::string& msg);
static int show(const std::string& msg);
private:
void processString(std::string& buf);

View File

@ -88,6 +88,7 @@ endif()
add_subdirectory(harfbuzz-cmake)
add_subdirectory(simpleini)
add_subdirectory(fmt)
# Add cmark without tests
if(NOT USE_SHARED_CMARK)

1
third_party/fmt vendored Submodule

@ -0,0 +1 @@
Subproject commit 933a33a7948c3d9bb984473b9b92832f52c590cd