feat(client/lang): full UI i18n impl for each language

This commit is contained in:
Zhongheng Liu 2026-01-23 22:41:35 +01:00
commit 9b1147c6c0
Signed by: steven
GPG key ID: F69B980899C1C09D
27 changed files with 507 additions and 238 deletions

View file

@ -56,6 +56,7 @@ public class FoodpalApplicationCtrl implements LocaleAware {
private final LocaleManager localeManager;
private final WebSocketDataService<Long, Recipe> dataService;
private final Logger logger = Logger.getLogger(FoodpalApplicationCtrl.class.getName());
public Button shoppingListButton;
@FXML
private RecipeDetailCtrl recipeDetailController;
@ -304,13 +305,13 @@ public class FoodpalApplicationCtrl implements LocaleAware {
@Override
public void updateText() {
recipesLabel.setText(getLocaleString("app.word.recipe.n"));
addRecipeButton.setText(getLocaleString("menu.button.add.recipe"));
removeRecipeButton.setText(getLocaleString("menu.button.remove.recipe"));
cloneRecipeButton.setText(getLocaleString("menu.button.clone"));
recipesLabel.setText(getLocaleString("menu.label.recipes"));
favouritesOnlyToggle.setText(getLocaleString("menu.button.favourites"));
manageIngredientsButton.setText(getLocaleString("menu.button.ingredients"));
shoppingListButton.setText(getLocaleString("app.list"));
manageIngredientsButton.setText(getLocaleString("app.word.ingredient.n"));
}
@Override
@ -517,7 +518,7 @@ public class FoodpalApplicationCtrl implements LocaleAware {
public void openShoppingListWindow() throws IOException {
var root = UI.getFXML().load(ShoppingListCtrl.class, "client", "scenes", "shopping", "ShoppingList.fxml");
Stage stage = new Stage();
stage.setTitle(this.getLocaleString("menu.shopping.title"));
stage.setTitle(this.getLocaleString("app.list"));
stage.setScene(new Scene(root.getValue()));
stage.show();
}

View file

@ -58,7 +58,7 @@ public class IngredientListCtrl implements LocaleAware {
ingredientsLabel.setText(getLocaleString("menu.label.ingredients"));
addButton.setText(getLocaleString("menu.button.add"));
refreshButton.setText(getLocaleString("menu.button.refresh"));
deleteButton.setText(getLocaleString("menu.button.delete"));
deleteButton.setText(getLocaleString("verb.delete"));
closeButton.setText(getLocaleString("menu.button.close"));
}

View file

@ -66,7 +66,17 @@ public class NutritionDetailsCtrl implements LocaleAware {
this.proteinInputElement.textProperty().bindBidirectional(vm.proteinProperty(), new NumberStringConverter());
this.carbInputElement.textProperty().bindBidirectional(vm.carbsProperty(), new NumberStringConverter());
this.estimatedKcalLabel.textProperty().bind(Bindings.createStringBinding(
() -> String.format("Estimated energy value: %.1f kcal/100g", vm.getKcal()), vm.kcalProperty()
() -> String.format(getLocaleString("app.kcal") + " %.1f kcal/100g", vm.getKcal()), vm.kcalProperty()
));
this.usageLabel.textProperty().bind(Bindings.createStringBinding(
() -> {
Long id = this.ingredient.get().toIngredient().getId();
logger.info("Fetching usage for ingredient ID: " + id);
return !id.equals(0L) ? String.format(
getLocaleString("app.label.usage.part") + " %d " + getLocaleString("app.word.recipe.n"),
server.getIngredientUsage(id)) : "";
},
this.ingredient.get().idProperty()
));
});
this.nutritionValueContainer.addEventHandler(KeyEvent.KEY_RELEASED, event -> {

View file

@ -1,5 +1,7 @@
package client.scenes.recipe;
import client.utils.LocaleAware;
import client.utils.LocaleManager;
import client.utils.server.ServerUtils;
import com.google.inject.Inject;
import commons.FormalIngredient;
@ -32,13 +34,18 @@ import java.util.logging.Logger;
*
* @see IngredientListCtrl
*/
public class IngredientListCell extends OrderedEditableListCell<RecipeIngredient> {
public class IngredientListCell extends OrderedEditableListCell<RecipeIngredient> implements LocaleAware {
private final ServerUtils server;
private final LocaleManager locale;
private final Logger logger = Logger.getLogger(IngredientListCell.class.getName());
private final SimpleObjectProperty<Ingredient> selectedIngredient = new SimpleObjectProperty<>();
@Inject
public IngredientListCell(ServerUtils server) {
public IngredientListCell(
ServerUtils server,
LocaleManager locale
) {
this.server = server;
this.locale = locale;
}
@Override
public void commitEdit(RecipeIngredient newValue) {
@ -101,11 +108,11 @@ public class IngredientListCell extends OrderedEditableListCell<RecipeIngredient
Consumer<T> onSelect,
HBox container) {
MenuItem newIngredientItem = new MenuItem();
newIngredientItem.setText("Something new...");
newIngredientItem.setText(getLocaleString("app.prompt.something-new"));
// on new ingredient click
newIngredientItem.setOnAction(_ -> {
menu.setText("New Ingredient"); // otherwise the text label on menu refuses to update
menu.setText(getLocaleString("app.prompt.new-ingredient")); // otherwise the text label on menu refuses to update
selectedIngredient.setValue(null); // indicate null to signal a new ingredient creation
logger.info("Making new ingredient");
// TODO printError() integration
@ -128,7 +135,7 @@ public class IngredientListCell extends OrderedEditableListCell<RecipeIngredient
}
}
private HBox makeInputLine(RecipeIngredient ingredient, TextField amountInput, ChoiceBox<Unit> unitChoice) {
MenuButton ingredientSelect = new MenuButton("Select your ingredient");
MenuButton ingredientSelect = new MenuButton(getLocaleString("app.prompt.select-ingredient"));
HBox container = new HBox(amountInput, unitChoice, ingredientSelect);
try {
makeMenuItems(ingredientSelect, server.getIngredients(), Ingredient::getName, i -> {
@ -163,7 +170,7 @@ public class IngredientListCell extends OrderedEditableListCell<RecipeIngredient
}
private @NonNull TextField makeNewIngredientNameField(Consumer<Ingredient> onSubmit) {
TextField newIngredientNameInput = new TextField("New ingredient...");
TextField newIngredientNameInput = new TextField(getLocaleString("app.prompt.new-ingredient"));
newIngredientNameInput.setOnKeyReleased(e -> {
if (e.getCode() != KeyCode.ENTER) {
return;
@ -183,4 +190,14 @@ public class IngredientListCell extends OrderedEditableListCell<RecipeIngredient
});
return newIngredientNameInput;
}
@Override
public void updateText() {
}
@Override
public LocaleManager getLocaleManager() {
return locale;
}
}

View file

@ -173,7 +173,7 @@ public class IngredientListCtrl implements LocaleAware {
this.ingredientListView.setEditable(true);
this.ingredientListView.setCellFactory(
list -> {
return new IngredientListCell(this.server);
return new IngredientListCell(this.server, this.localeManager);
});
this.ingredientListView.setOnEditCommit(this::handleIngredientEdit);

View file

@ -60,6 +60,9 @@ public class RecipeDetailCtrl implements LocaleAware {
public Label inferredKcalLabel;
public Spinner<Integer> servingsSpinner;
public Label inferredServeSizeLabel;
public Label scaleLabel;
public Label servingLabel;
public Button addToListButton;
@FXML
private IngredientListCtrl ingredientListController;
@ -178,13 +181,13 @@ public class RecipeDetailCtrl implements LocaleAware {
this.recipeView = new ScalableRecipeView(recipe, scale);
// TODO i18n
inferredKcalLabel.textProperty().bind(Bindings.createStringBinding(() ->
String.format("Inferred %.1f kcal/100g for this recipe",
String.format(getLocaleString("app.label.inferred-kcal") + " %.1f kcal/100g",
Double.isNaN(this.recipeView.scaledKcalProperty().get()) ?
0.0 : this.recipeView.scaledKcalProperty().get())
, this.recipeView.scaledKcalProperty()));
recipeView.servingsProperty().set(servingsSpinner.getValue());
inferredServeSizeLabel.textProperty().bind(Bindings.createStringBinding(
() -> String.format("Inferred size per serving: %.1f g", recipeView.servingSizeProperty().get()),
() -> String.format(getLocaleString("app.label.inferred-size") + " %.1f g", recipeView.servingSizeProperty().get()),
recipeView.servingSizeProperty()));
// expose the scaled view to list controllers
this.ingredientListController.refetchFromRecipe(this.recipeView.getScaled());
@ -405,6 +408,9 @@ public class RecipeDetailCtrl implements LocaleAware {
editRecipeTitleButton.setText(getLocaleString("menu.button.edit"));
removeRecipeButton.setText(getLocaleString("menu.button.remove.recipe"));
printRecipeButton.setText(getLocaleString("menu.button.print"));
addToListButton.setText(getLocaleString("app.word.shop"));
scaleLabel.setText(getLocaleString("app.word.scale"));
servingLabel.setText(getLocaleString("app.word.serving.n"));
}
@Override

View file

@ -14,6 +14,8 @@ import javafx.beans.property.StringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.TextInputDialog;
@ -31,6 +33,11 @@ public class AddOverviewCtrl implements LocaleAware {
private final ShoppingListService shoppingListService;
private final LocaleManager localeManager;
public Button addButton;
public Button removeSelButton;
public Button cancelButton;
public Button addConfirmButton;
public Label addOverviewTitle;
private String sourceRecipeName;
@ -88,6 +95,13 @@ public class AddOverviewCtrl implements LocaleAware {
@Override
public void updateText() {
amountColumn.setText(getLocaleString("app.word.amount"));
unitColumn.setText(getLocaleString("app.word.unit"));
nameColumn.setText(getLocaleString("app.word.ingredient"));
addButton.setText(getLocaleString("verb.add"));
cancelButton.setText(getLocaleString("verb.cancel"));
addConfirmButton.setText(getLocaleString("verb.addconfirm"));
removeSelButton.setText(getLocaleString("verb.removesel"));
}
@Override

View file

@ -13,7 +13,9 @@ import javafx.scene.Node;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Alert;
import javafx.scene.control.Button;
import javafx.scene.control.ListView;
import javafx.scene.control.TitledPane;
import javafx.stage.FileChooser;
import javafx.stage.Modality;
import javafx.stage.Stage;
@ -23,6 +25,11 @@ import java.io.File;
import java.util.Optional;
public class ShoppingListCtrl implements LocaleAware {
public Button addItemButton;
public Button deleteItemButton;
public Button printButton;
public Button resetButton;
public TitledPane shoppingListContainer;
ShoppingListService shopping;
LocaleManager localeManager;
@ -40,7 +47,11 @@ public class ShoppingListCtrl implements LocaleAware {
@Override
public void updateText() {
shoppingListContainer.setText(getLocaleString("app.list"));
addItemButton.setText(getLocaleString("verb.add"));
deleteItemButton.setText(getLocaleString("verb.delete"));
resetButton.setText(getLocaleString("verb.reset"));
printButton.setText(getLocaleString("verb.print"));
}
@Override

View file

@ -10,6 +10,7 @@ import commons.Unit;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.event.ActionEvent;
import javafx.scene.control.Button;
import javafx.scene.control.MenuButton;
import javafx.scene.control.MenuItem;
import javafx.scene.control.Spinner;
@ -27,6 +28,8 @@ public class ShoppingListNewItemPromptCtrl implements LocaleAware {
private final ObjectProperty<Unit> selectedUnit = new SimpleObjectProperty<>();
private final ServerUtils server;
private final LocaleManager localeManager;
public Button confirmButton;
public Button cancelButton;
private Consumer<FormalIngredient> newValueConsumer;
public MenuButton unitSelect;
public Spinner<Double> amountSelect;
@ -72,7 +75,10 @@ public class ShoppingListNewItemPromptCtrl implements LocaleAware {
}
@Override
public void updateText() {
unitSelect.setText(getLocaleString("app.word.unit"));
ingredientSelection.setText(getLocaleString("app.word.ingredient"));
confirmButton.setText(getLocaleString("verb.confirm"));
cancelButton.setText(getLocaleString("verb.cancel"));
}
@Override
public void initializeComponents() {

View file

@ -5,7 +5,7 @@ import java.util.List;
public class Config {
private String language = "en";
public static String[] languages = {"en", "nl", "pl", "tok", "zhc", "zht"};
public static String[] languages = {"en", "nl", "pl", "tr", "tok", "zhc", "zht"};
private List<String> recipeLanguages = new ArrayList<>();
private String serverUrl = "http://localhost:8080";

View file

@ -52,7 +52,7 @@
</padding>
<fx:include source="LangSelect.fxml" />
<Button fx:id="refreshButton" onAction="#refresh" prefHeight="25.0" prefWidth="34.0" text="⟳" GridPane.columnIndex="3" GridPane.rowIndex="2" />
<Label fx:id="recipesLabel" text="Recipes">
<Label fx:id="recipesLabel" text="%app.word.recipe.n">
<font>
<Font name="System Bold" size="15.0" />
</font>
@ -64,18 +64,18 @@
<ListView fx:id="recipeList" />
<HBox spacing="10">
<Button fx:id="addRecipeButton" onAction="#addRecipe" text="Add Recipe" />
<Button fx:id="removeRecipeButton" onAction="#removeSelectedRecipe" text="Remove Recipe" />
<Button fx:id="cloneRecipeButton" mnemonicParsing="false" onAction="#cloneRecipe" text="Clone" />
<ToggleButton fx:id="favouritesOnlyToggle" text="Favourites" onAction="#toggleFavouritesView" />
<Button fx:id="addRecipeButton" onAction="#addRecipe" text="%menu.button.add.recipe" />
<Button fx:id="removeRecipeButton" onAction="#removeSelectedRecipe" text="%menu.button.remove.recipe" />
<Button fx:id="cloneRecipeButton" mnemonicParsing="false" onAction="#cloneRecipe" text="%menu.button.clone" />
<ToggleButton fx:id="favouritesOnlyToggle" text="%menu.button.favourites" onAction="#toggleFavouritesView" />
</HBox>
<Button fx:id="shoppingListButton"
onAction="#openShoppingListWindow"
text="Shopping List" />
text="%app.list" />
<Button fx:id="manageIngredientsButton"
onAction="#openIngredientsPopup"
text="Ingredients..." />
text="%app.word.ingredient.n" />
</VBox>
</left>
@ -95,7 +95,7 @@
<Insets bottom="16" left="16" right="16" top="8" />
</padding>
<Label fx:id="updatedBadge"
text="Updated just now"
text="%app.updated"
visible="false"
managed="false"
styleClass="updated-badge"/>

View file

@ -6,6 +6,6 @@
<HBox xmlns="http://javafx.com/javafx/25" xmlns:fx="http://javafx.com/fxml/1" fx:controller="client.scenes.SearchBarCtrl">
<children>
<TextField fx:id="searchField" promptText="Search..." />
<TextField fx:id="searchField" promptText="%menu.search" />
</children>
</HBox>

View file

@ -21,7 +21,7 @@
<Label GridPane.columnIndex="0" GridPane.rowIndex="2" fx:id="carbInputLabel">Carbohydrates: </Label>
<TextField GridPane.columnIndex="1" GridPane.rowIndex="2" fx:id="carbInputElement" />
</GridPane>
<Button onAction="#handleNutritionSaveClick">Save values</Button>
<Label fx:id="estimatedKcalLabel">Estimated: 0kcal</Label>
<Label fx:id="usageLabel">Not used in any recipes</Label>
<Button onAction="#handleNutritionSaveClick" text="%verb.save" />
<Label fx:id="estimatedKcalLabel" />
<Label fx:id="usageLabel" />
</VBox>

View file

@ -21,18 +21,18 @@
<HBox spacing="10">
<HBox fx:id="editableTitleArea">
</HBox>
<Button fx:id="editRecipeTitleButton" onAction="#editRecipeTitle" text="Edit" />
<Button fx:id="removeRecipeButton" mnemonicParsing="false" onAction="#removeSelectedRecipe" text="Remove Recipe" />
<Button fx:id="printRecipeButton" mnemonicParsing="false" onAction="#printRecipe" text="Print Recipe" />
<Button fx:id="editRecipeTitleButton" onAction="#editRecipeTitle" text="%menu.button.edit" />
<Button fx:id="removeRecipeButton" mnemonicParsing="false" onAction="#removeSelectedRecipe" text="%menu.button.remove.recipe" />
<Button fx:id="printRecipeButton" mnemonicParsing="false" onAction="#printRecipe" text="%menu.button.print" />
<Button fx:id="favouriteButton" onAction="#toggleFavourite" text="☆" />
<Button onAction="#handleAddAllToShoppingList">Shop</Button>
<Button fx:id="addToListButton" onAction="#handleAddAllToShoppingList" text="%app.word.shop" />
</HBox>
<HBox>
<ComboBox fx:id="langSelector" onAction="#changeLanguage" />
<Label>Scale: </Label>
<Label fx:id="scaleLabel" text="%app.word.scale" />
<Spinner fx:id="scaleSpinner" />
<Label>Servings: </Label>
<Label fx:id="servingLabel" text="%app.word.serving.n" />
<Spinner fx:id="servingsSpinner" />
</HBox>

View file

@ -16,7 +16,7 @@
<children>
<HBox alignment="CENTER_LEFT" spacing="20.0">
<children>
<Label fx:id="ingredientsLabel" text="Ingredients">
<Label fx:id="ingredientsLabel" text="%app.word.ingredient.n">
<padding>
<Insets bottom="5.0" top="5.0" />
</padding>
@ -26,8 +26,8 @@
</Label>
<HBox alignment="CENTER" spacing="10.0">
<children>
<Button fx:id="addIngredientButton" mnemonicParsing="false" text="Add" />
<Button fx:id="deleteIngredientButton" mnemonicParsing="false" text="Delete" />
<Button fx:id="addIngredientButton" mnemonicParsing="false" text="%verb.add" />
<Button fx:id="deleteIngredientButton" mnemonicParsing="false" text="%verb.delete" />
</children>
</HBox>
</children>

View file

@ -15,7 +15,7 @@
<children>
<HBox alignment="CENTER_LEFT" spacing="20.0">
<children>
<Label fx:id="stepsLabel" text="Steps">
<Label fx:id="stepsLabel" text="%app.word.step.n">
<padding>
<Insets bottom="5.0" top="5.0" />
</padding>
@ -25,8 +25,8 @@
</Label>
<HBox alignment="CENTER" spacing="10.0">
<children>
<Button fx:id="addStepButton" mnemonicParsing="false" text="Add" />
<Button fx:id="deleteStepButton" mnemonicParsing="false" text="Delete" />
<Button fx:id="addStepButton" mnemonicParsing="false" text="%verb.add" />
<Button fx:id="deleteStepButton" mnemonicParsing="false" text="%verb.delete" />
</children>
</HBox>
</children>

View file

@ -11,22 +11,22 @@
<VBox spacing="10.0" AnchorPane.topAnchor="10.0" AnchorPane.leftAnchor="10.0"
AnchorPane.rightAnchor="10.0" AnchorPane.bottomAnchor="10.0">
<Label text="Review ingredients before adding" />
<Label fx:id="addOverviewTitle" text="%app.title.addoverview" />
<TableView fx:id="overviewTable" editable="true" VBox.vgrow="ALWAYS">
<columns>
<TableColumn fx:id="nameColumn" text="Ingredient" prefWidth="360.0"/>
<TableColumn fx:id="amountColumn" text="Amount" prefWidth="140.0"/>
<TableColumn fx:id="unitColumn" text="Unit" prefWidth="140.0"/>
<TableColumn fx:id="nameColumn" text="%app.word.ingredient" prefWidth="360.0"/>
<TableColumn fx:id="amountColumn" text="%app.word.amount" prefWidth="140.0"/>
<TableColumn fx:id="unitColumn" text="%app.word.unit" prefWidth="140.0"/>
</columns>
</TableView>
<HBox spacing="10.0">
<Button text="Add item" onAction="#handleAddRow"/>
<Button text="Remove selected" onAction="#handleRemoveSelected"/>
<Button fx:id="addButton" text="%verb.add" onAction="#handleAddRow"/>
<Button fx:id="removeSelButton" text="%verb.removesel" onAction="#handleRemoveSelected"/>
<Pane HBox.hgrow="ALWAYS"/>
<Button text="Cancel" onAction="#handleCancel"/>
<Button text="Confirm &amp; Add" onAction="#handleConfirm"/>
<Button fx:id="cancelButton" text="%verb.cancel" onAction="#handleCancel"/>
<Button fx:id="addConfirmButton" text="%verb.addconfirm" onAction="#handleConfirm"/>
</HBox>
</VBox>
</AnchorPane>

View file

@ -8,7 +8,7 @@
<?import javafx.scene.control.Button?>
<?import javafx.scene.layout.VBox?>
<TitledPane animated="false" collapsible="false" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity"
minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" text="Shopping List"
minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" text="%app.list" fx:id="shoppingListContainer"
fx:controller="client.scenes.shopping.ShoppingListCtrl"
xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/25">
<VBox>
@ -16,10 +16,10 @@
AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0"
AnchorPane.topAnchor="0.0"/>
<HBox>
<Button onAction="#handleAddItem">Add</Button>
<Button onAction="#handleRemoveItem">Delete</Button>
<Button onAction="#handlePrint">Print</Button>
<Button onAction="#handleReset">Reset</Button>
<Button fx:id="addItemButton" onAction="#handleAddItem" />
<Button fx:id="deleteItemButton" onAction="#handleRemoveItem" />
<Button fx:id="printButton" onAction="#handlePrint" />
<Button fx:id="resetButton" onAction="#handleReset" />
</HBox>
</VBox>
</TitledPane>

View file

@ -17,8 +17,8 @@
<MenuButton fx:id="ingredientSelection">Your ingredient...</MenuButton>
</HBox>
<HBox>
<Button onAction="#confirmAdd">Confirm</Button>
<Button onAction="#cancelAdd">Cancel</Button>
<Button fx:id="confirmButton" onAction="#confirmAdd">Confirm</Button>
<Button fx:id="cancelButton" onAction="#cancelAdd">Cancel</Button>
</HBox>
</VBox>
</AnchorPane>

View file

@ -1,15 +1,3 @@
add.ingredient.title=Add Ingredient
add.recipe.title=Create recipe
add.step.title=Add Step
add.ingredient.label=Ingredient
add.recipe.label=Recipe Name
add.step.label=Step
button.ok=Ok
button.cancel=Cancel
menu.label.recipes=Recipes
menu.label.ingredients=Ingredients
menu.label.preparation=Preparation
@ -17,7 +5,7 @@ menu.button.add.recipe=Add Recipe
menu.button.add.ingredient=Add Ingredient
menu.button.add.step=Add Step
menu.button.favourites=Favourites
menu.button.ingredients=Ingredients
menu.button.remove.recipe=Remove Recipe
menu.button.remove.ingredient=Remove Ingredient
@ -31,9 +19,42 @@ menu.ingredients.title=Nutrition value
menu.button.add=Add
menu.button.refresh=Refresh
menu.button.delete=Delete
menu.button.close=Close
app.word.recipe.n=Recipes
app.updated=Updated just now
app.estimated=Estimated:
app.prompt.something-new=Something new...
app.prompt.new-ingredient=New ingredient...
app.prompt.select-ingredient=Select your ingredient
app.kcal=Estimated energy value:
app.label.usage.part=Used in
app.list=Shopping List
app.title.addoverview=Review ingredients before adding
app.label.inferred-kcal=Inferred calories for this recipe:
app.label.inferred-size=Inferred serving size:
app.word.amount=Amount
app.word.unit=Unit
app.word.shop=Shop
app.word.scale=Scale
app.word.serving.n=Servings
app.word.step.1=Step
app.word.step.n=Steps
app.word.ingredient=Ingredient
app.word.ingredient.n=Ingredients
verb.cancel=Cancel
verb.save=Save
verb.delete=Delete
verb.add=Add
verb.print=Print
verb.reset=Reset
verb.removesel=Remove selected
verb.addconfirm=Confirm and Add
menu.search=Search...
menu.label.selected-langs=Languages

Some files were not shown because too many files have changed in this diff Show more