diff --git a/changelog/66_UNRELEASED_xxxx-xx-xx.md b/changelog/66_UNRELEASED_xxxx-xx-xx.md
index f5ca33d5..aa8a5dda 100644
--- a/changelog/66_UNRELEASED_xxxx-xx-xx.md
+++ b/changelog/66_UNRELEASED_xxxx-xx-xx.md
@@ -11,6 +11,7 @@
- Fixed that when adding missing recipe ingredients, with the option "Only check if any amount is in stock" enabled, to the shopping list, unit conversions (if any) weren't considered
- Fixed that the recipe stock fulfillment information about shopping list amounts was not correct when the ingredient had a decimal amount
- Fixed that the meal plan showed the total calories per recipe (instead of per serving as stated by the suffix)
+- Fixed that when having a quantity unit matching any application string, the translation of that string was used to display that unit
- Fixed that formatted (HTML) text for the (hidden by default) product description column on the stock overview page was not correctly displayed
- Fixed that numeric and date-time sorting of table columns on the stock entries page did not work correctly (thanks @MasterofJOKers)
- Fixed that the barcode lookup for the "Stock by-barcode" API endpoints was case sensitive
diff --git a/controllers/BaseController.php b/controllers/BaseController.php
index 9d14e15d..59a65a37 100644
--- a/controllers/BaseController.php
+++ b/controllers/BaseController.php
@@ -126,10 +126,11 @@ class BaseController
$this->View->set('__t', function (string $text, ...$placeholderValues) use ($localizationService) {
return $localizationService->__t($text, $placeholderValues);
});
- $this->View->set('__n', function ($number, $singularForm, $pluralForm) use ($localizationService) {
- return $localizationService->__n($number, $singularForm, $pluralForm);
+ $this->View->set('__n', function ($number, $singularForm, $pluralForm, $isQu = false) use ($localizationService) {
+ return $localizationService->__n($number, $singularForm, $pluralForm, $isQu);
});
$this->View->set('LocalizationStrings', $localizationService->GetPoAsJsonString());
+ $this->View->set('LocalizationStringsQu', $localizationService->GetPoAsJsonStringQu());
// TODO: Better handle this generically based on the current language (header in .po file?)
$dir = 'ltr';
diff --git a/public/js/grocy.js b/public/js/grocy.js
index a896fba9..4557f746 100644
--- a/public/js/grocy.js
+++ b/public/js/grocy.js
@@ -232,6 +232,7 @@ U = function(relativePath)
}
Grocy.Translator = new Translator(Grocy.LocalizationStrings);
+Grocy.TranslatorQu = new Translator(Grocy.LocalizationStringsQu);
__t = function(text, ...placeholderValues)
{
if (Grocy.Mode === "dev")
@@ -245,7 +246,7 @@ __t = function(text, ...placeholderValues)
return Grocy.Translator.__(text, ...placeholderValues)
}
-__n = function(number, singularForm, pluralForm)
+__n = function(number, singularForm, pluralForm, isQu = false)
{
if (Grocy.Mode === "dev")
{
@@ -256,7 +257,14 @@ __n = function(number, singularForm, pluralForm)
}
}
- return Grocy.Translator.n__(singularForm, pluralForm, Math.abs(number), Math.abs(number))
+ if (isQu)
+ {
+ return Grocy.TranslatorQu.n__(singularForm, pluralForm, Math.abs(number), Math.abs(number))
+ }
+ else
+ {
+ return Grocy.Translator.n__(singularForm, pluralForm, Math.abs(number), Math.abs(number))
+ }
}
if (!Grocy.ActiveNav.isEmpty())
diff --git a/public/viewjs/components/productamountpicker.js b/public/viewjs/components/productamountpicker.js
index 1f75221f..bb085286 100644
--- a/public/viewjs/components/productamountpicker.js
+++ b/public/viewjs/components/productamountpicker.js
@@ -94,7 +94,7 @@ $(".input-group-productamountpicker").on("change", function()
var quFactor = $("#qu_id option:selected").attr("data-qu-factor");
var amount = $("#display_amount").val();
var destinationAmount = amount / quFactor;
- var destinationQuName = __n(destinationAmount, $("#qu_id").attr("data-destination-qu-name"), $("#qu_id").attr("data-destination-qu-name-plural"))
+ var destinationQuName = __n(destinationAmount, $("#qu_id").attr("data-destination-qu-name"), $("#qu_id").attr("data-destination-qu-name-plural"), true);
if ($("#qu_id").attr("data-destination-qu-name") == selectedQuName || Grocy.Components.ProductAmountPicker.AllowAnyQuEnabled || amount.toString().isEmpty() || selectedQuName.toString().isEmpty())
{
diff --git a/public/viewjs/components/productcard.js b/public/viewjs/components/productcard.js
index 97436a25..20812f4e 100644
--- a/public/viewjs/components/productcard.js
+++ b/public/viewjs/components/productcard.js
@@ -11,7 +11,7 @@ Grocy.Components.ProductCard.Refresh = function(productId)
$('#productcard-product-name').text(productDetails.product.name);
$('#productcard-product-description').html(productDetails.product.description);
$('#productcard-product-stock-amount').text(stockAmount);
- $('#productcard-product-stock-qu-name').text(__n(stockAmount, productDetails.quantity_unit_stock.name, productDetails.quantity_unit_stock.name_plural));
+ $('#productcard-product-stock-qu-name').text(__n(stockAmount, productDetails.quantity_unit_stock.name, productDetails.quantity_unit_stock.name_plural, true));
$('#productcard-product-stock-value').text(stockValue + ' ' + Grocy.Currency);
$('#productcard-product-last-purchased').text((productDetails.last_purchased || '2999-12-31').substring(0, 10));
$('#productcard-product-last-purchased-timeago').attr("datetime", productDetails.last_purchased || '2999-12-31');
@@ -26,7 +26,7 @@ Grocy.Components.ProductCard.Refresh = function(productId)
if (productDetails.is_aggregated_amount == 1)
{
$('#productcard-product-stock-amount-aggregated').text(productDetails.stock_amount_aggregated);
- $('#productcard-product-stock-qu-name-aggregated').text(__n(productDetails.stock_amount_aggregated, productDetails.quantity_unit_stock.name, productDetails.quantity_unit_stock.name_plural));
+ $('#productcard-product-stock-qu-name-aggregated').text(__n(productDetails.stock_amount_aggregated, productDetails.quantity_unit_stock.name, productDetails.quantity_unit_stock.name_plural, true));
if (productDetails.stock_amount_opened_aggregated > 0)
{
diff --git a/public/viewjs/consume.js b/public/viewjs/consume.js
index 49f7f5b3..f8d9c431 100644
--- a/public/viewjs/consume.js
+++ b/public/viewjs/consume.js
@@ -77,11 +77,11 @@
if (productDetails.product.enable_tare_weight_handling == 1 && !jsonData.exact_amount)
{
- var successMessage = __t('Removed %1$s of %2$s from stock', Math.abs(jsonForm.amount - (parseFloat(productDetails.product.tare_weight) + parseFloat(productDetails.stock_amount))) + " " + __n(jsonForm.amount, productDetails.quantity_unit_stock.name, productDetails.quantity_unit_stock.name_plural), productDetails.product.name) + '
' + __t("Undo") + '';
+ var successMessage = __t('Removed %1$s of %2$s from stock', Math.abs(jsonForm.amount - (parseFloat(productDetails.product.tare_weight) + parseFloat(productDetails.stock_amount))) + " " + __n(jsonForm.amount, productDetails.quantity_unit_stock.name, productDetails.quantity_unit_stock.name_plural, true), productDetails.product.name) + '
' + __t("Undo") + '';
}
else
{
- var successMessage = __t('Removed %1$s of %2$s from stock', Math.abs(jsonForm.amount) + " " + __n(jsonForm.amount, productDetails.quantity_unit_stock.name, productDetails.quantity_unit_stock.name_plural), productDetails.product.name) + '
' + __t("Undo") + '';
+ var successMessage = __t('Removed %1$s of %2$s from stock', Math.abs(jsonForm.amount) + " " + __n(jsonForm.amount, productDetails.quantity_unit_stock.name, productDetails.quantity_unit_stock.name_plural, true), productDetails.product.name) + '
' + __t("Undo") + '';
}
if (GetUriParam("embedded") !== undefined)
@@ -177,7 +177,7 @@ $('#save-mark-as-open-button').on('click', function(e)
}
Grocy.FrontendHelpers.EndUiBusy("consume-form");
- toastr.success(__t('Marked %1$s of %2$s as opened', parseFloat(jsonForm.amount).toLocaleString({ minimumFractionDigits: 0, maximumFractionDigits: Grocy.UserSettings.stock_decimal_places_amounts }) + " " + __n(jsonForm.amount, productDetails.quantity_unit_stock.name, productDetails.quantity_unit_stock.name_plural), productDetails.product.name) + '
' + __t("Undo") + '');
+ toastr.success(__t('Marked %1$s of %2$s as opened', parseFloat(jsonForm.amount).toLocaleString({ minimumFractionDigits: 0, maximumFractionDigits: Grocy.UserSettings.stock_decimal_places_amounts }) + " " + __n(jsonForm.amount, productDetails.quantity_unit_stock.name, productDetails.quantity_unit_stock.name_plural, true), productDetails.product.name) + '
' + __t("Undo") + '');
if (BoolVal(Grocy.UserSettings.stock_default_consume_amount_use_quick_consume_amount))
{
diff --git a/public/viewjs/inventory.js b/public/viewjs/inventory.js
index 38e7a6da..0500ab31 100644
--- a/public/viewjs/inventory.js
+++ b/public/viewjs/inventory.js
@@ -114,7 +114,7 @@
Grocy.Api.Get('stock/products/' + jsonForm.product_id,
function(result)
{
- var successMessage = __t('Stock amount of %1$s is now %2$s', result.product.name, result.stock_amount + " " + __n(result.stock_amount, result.quantity_unit_stock.name, result.quantity_unit_stock.name_plural)) + '
' + __t("Undo") + '';
+ var successMessage = __t('Stock amount of %1$s is now %2$s', result.product.name, result.stock_amount + " " + __n(result.stock_amount, result.quantity_unit_stock.name, result.quantity_unit_stock.name_plural, true)) + '
' + __t("Undo") + '';
if (GetUriParam("embedded") !== undefined)
{
@@ -384,7 +384,7 @@ $('#display_amount').on('keyup', function(e)
}
else if (newAmount > productStockAmount + containerWeight)
{
- $('#inventory-change-info').text(__t('This means %s will be added to stock', estimatedBookingAmount.toLocaleString() + ' ' + __n(estimatedBookingAmount, productDetails.quantity_unit_stock.name, productDetails.quantity_unit_stock.name_plural)));
+ $('#inventory-change-info').text(__t('This means %s will be added to stock', estimatedBookingAmount.toLocaleString() + ' ' + __n(estimatedBookingAmount, productDetails.quantity_unit_stock.name, productDetails.quantity_unit_stock.name_plural, true)));
Grocy.Components.DateTimePicker.GetInputElement().attr('required', '');
if (Grocy.FeatureFlags.GROCY_FEATURE_FLAG_STOCK_LOCATION_TRACKING)
{
@@ -393,7 +393,7 @@ $('#display_amount').on('keyup', function(e)
}
else if (newAmount < productStockAmount + containerWeight)
{
- $('#inventory-change-info').text(__t('This means %s will be removed from stock', estimatedBookingAmount.toLocaleString() + ' ' + __n(estimatedBookingAmount, productDetails.quantity_unit_stock.name, productDetails.quantity_unit_stock.name_plural)));
+ $('#inventory-change-info').text(__t('This means %s will be removed from stock', estimatedBookingAmount.toLocaleString() + ' ' + __n(estimatedBookingAmount, productDetails.quantity_unit_stock.name, productDetails.quantity_unit_stock.name_plural, true)));
Grocy.Components.DateTimePicker.GetInputElement().removeAttr('required');
if (Grocy.FeatureFlags.GROCY_FEATURE_FLAG_STOCK_LOCATION_TRACKING)
{
diff --git a/public/viewjs/mealplan.js b/public/viewjs/mealplan.js
index 71b3b67e..91fcbadd 100644
--- a/public/viewjs/mealplan.js
+++ b/public/viewjs/mealplan.js
@@ -252,13 +252,13 @@ $(".calendar").each(function()
element.html('\
\
' + productDetails.product.name + '
\
-
' + mealPlanEntry.product_amount + " " + __n(mealPlanEntry.product_amount, productDetails.quantity_unit_stock.name, productDetails.quantity_unit_stock.name_plural) + '
\
+
' + mealPlanEntry.product_amount + " " + __n(mealPlanEntry.product_amount, productDetails.quantity_unit_stock.name, productDetails.quantity_unit_stock.name_plural, true) + '
\
' + fulfillmentIconHtml + " " + fulfillmentInfoHtml + '
\
' + costsAndCaloriesPerServing + ' \
\
\
\
- \
+ \
' + shoppingListButtonHtml + ' \
' + doneButtonHtml + ' \
\
@@ -800,7 +800,7 @@ $(document).on('click', '.product-consume-button', function(e)
Grocy.Api.Get('stock/products/' + productId,
function(result)
{
- var toastMessage = __t('Removed %1$s of %2$s from stock', consumeAmount.toString() + " " + __n(consumeAmount, result.quantity_unit_stock.name, result.quantity_unit_stock.name_plural), result.product.name) + '
' + __t("Undo") + '';
+ var toastMessage = __t('Removed %1$s of %2$s from stock', consumeAmount.toString() + " " + __n(consumeAmount, result.quantity_unit_stock.name, result.quantity_unit_stock.name_plural, true), result.product.name) + '
' + __t("Undo") + '';
Grocy.Api.Put('objects/meal_plan/' + mealPlanEntryId, { "done": 1 },
function(result)
diff --git a/public/viewjs/productform.js b/public/viewjs/productform.js
index 882c2a57..ab5df14f 100644
--- a/public/viewjs/productform.js
+++ b/public/viewjs/productform.js
@@ -177,7 +177,7 @@ $('.input-group-qu').on('change', function(e)
if (factor > 1 || quIdPurchase != quIdStock)
{
- $('#qu-conversion-info').text(__t('This means 1 %1$s purchased will be converted into %2$s %3$s in stock', $("#qu_id_purchase option:selected").text(), (1 * factor).toString(), __n((1 * factor).toString(), $("#qu_id_stock option:selected").text(), $("#qu_id_stock option:selected").data("plural-form"))));
+ $('#qu-conversion-info').text(__t('This means 1 %1$s purchased will be converted into %2$s %3$s in stock', $("#qu_id_purchase option:selected").text(), (1 * factor).toString(), __n((1 * factor).toString(), $("#qu_id_stock option:selected").text(), $("#qu_id_stock option:selected").data("plural-form"), true)));
$('#qu-conversion-info').removeClass('d-none');
}
else
diff --git a/public/viewjs/purchase.js b/public/viewjs/purchase.js
index bd51110c..c340fba3 100644
--- a/public/viewjs/purchase.js
+++ b/public/viewjs/purchase.js
@@ -115,7 +115,7 @@ $('#save-purchase-button').on('click', function(e)
{
amountMessage = parseFloat(jsonForm.amount) - parseFloat(productDetails.stock_amount) - parseFloat(productDetails.product.tare_weight);
}
- var successMessage = __t('Added %1$s of %2$s to stock', amountMessage + " " + __n(amountMessage, productDetails.quantity_unit_stock.name, productDetails.quantity_unit_stock.name_plural), productDetails.product.name) + '
' + __t("Undo") + '';
+ var successMessage = __t('Added %1$s of %2$s to stock', amountMessage + " " + __n(amountMessage, productDetails.quantity_unit_stock.name, productDetails.quantity_unit_stock.name_plural, true), productDetails.product.name) + '
' + __t("Undo") + '';
if (Grocy.FeatureFlags.GROCY_FEATURE_FLAG_LABEL_PRINTER)
{
diff --git a/public/viewjs/quantityunitconversionform.js b/public/viewjs/quantityunitconversionform.js
index 61bec445..7f206d4b 100644
--- a/public/viewjs/quantityunitconversionform.js
+++ b/public/viewjs/quantityunitconversionform.js
@@ -179,12 +179,12 @@ $('.input-group-qu').on('change', function(e)
if (fromQuId && toQuId)
{
- $('#qu-conversion-info').text(__t('This means 1 %1$s is the same as %2$s %3$s', $("#from_qu_id option:selected").text(), parseFloat((1 * factor)).toLocaleString({ minimumFractionDigits: 0, maximumFractionDigits: Grocy.UserSettings.stock_decimal_places_amounts }), __n((1 * factor).toLocaleString({ minimumFractionDigits: 0, maximumFractionDigits: Grocy.UserSettings.stock_decimal_places_amounts }), $("#to_qu_id option:selected").text(), $("#to_qu_id option:selected").data("plural-form"))));
+ $('#qu-conversion-info').text(__t('This means 1 %1$s is the same as %2$s %3$s', $("#from_qu_id option:selected").text(), parseFloat((1 * factor)).toLocaleString({ minimumFractionDigits: 0, maximumFractionDigits: Grocy.UserSettings.stock_decimal_places_amounts }), __n((1 * factor).toLocaleString({ minimumFractionDigits: 0, maximumFractionDigits: Grocy.UserSettings.stock_decimal_places_amounts }), $("#to_qu_id option:selected").text(), $("#to_qu_id option:selected").data("plural-form"), true)));
$('#qu-conversion-info').removeClass('d-none');
if (Grocy.EditMode === 'create')
{
- $('#qu-conversion-inverse-info').text(__t('This means 1 %1$s is the same as %2$s %3$s', $("#to_qu_id option:selected").text(), parseFloat((1 / factor)).toLocaleString({ minimumFractionDigits: 0, maximumFractionDigits: Grocy.UserSettings.stock_decimal_places_amounts }), __n((1 / factor).toString(), $("#from_qu_id option:selected").text(), $("#from_qu_id option:selected").data("plural-form"))));
+ $('#qu-conversion-inverse-info').text(__t('This means 1 %1$s is the same as %2$s %3$s', $("#to_qu_id option:selected").text(), parseFloat((1 / factor)).toLocaleString({ minimumFractionDigits: 0, maximumFractionDigits: Grocy.UserSettings.stock_decimal_places_amounts }), __n((1 / factor).toString(), $("#from_qu_id option:selected").text(), $("#from_qu_id option:selected").data("plural-form"), true)));
$('#qu-conversion-inverse-info').removeClass('d-none');
}
}
diff --git a/public/viewjs/quantityunitpluraltesting.js b/public/viewjs/quantityunitpluraltesting.js
index 1e4169af..0ee08c16 100644
--- a/public/viewjs/quantityunitpluraltesting.js
+++ b/public/viewjs/quantityunitpluraltesting.js
@@ -25,7 +25,7 @@ function RefreshQuPluralTestingResult()
}
animateCSS("h2", "shake");
- $("#result").text(__n(amount, singularForm, pluralForm));
+ $("#result").text(__n(amount, singularForm, pluralForm, true));
}
if (GetUriParam("qu") !== undefined)
diff --git a/public/viewjs/shoppinglistitemform.js b/public/viewjs/shoppinglistitemform.js
index ab201a31..3e5fcf64 100644
--- a/public/viewjs/shoppinglistitemform.js
+++ b/public/viewjs/shoppinglistitemform.js
@@ -59,7 +59,7 @@ $('#save-shoppinglist-button').on('click', function(e)
Grocy.Api.Get('stock/products/' + jsonData.product_id,
function(productDetails)
{
- window.parent.postMessage(WindowMessageBag("ShowSuccessMessage", __t("Added %1$s of %2$s to the shopping list \"%3$s\"", displayAmount.toLocaleString({ minimumFractionDigits: 0, maximumFractionDigits: Grocy.UserSettings.stock_decimal_places_amounts }) + " " + __n(displayAmount, $("#qu_id option:selected").text(), $("#qu_id option:selected").attr("data-qu-name-plural")), productDetails.product.name, $("#shopping_list_id option:selected").text())), Grocy.BaseUrl);
+ window.parent.postMessage(WindowMessageBag("ShowSuccessMessage", __t("Added %1$s of %2$s to the shopping list \"%3$s\"", displayAmount.toLocaleString({ minimumFractionDigits: 0, maximumFractionDigits: Grocy.UserSettings.stock_decimal_places_amounts }) + " " + __n(displayAmount, $("#qu_id option:selected").text(), $("#qu_id option:selected").attr("data-qu-name-plural"), true), productDetails.product.name, $("#shopping_list_id option:selected").text())), Grocy.BaseUrl);
window.parent.postMessage(WindowMessageBag("ShoppingListChanged", $("#shopping_list_id").val().toString()), Grocy.BaseUrl);
window.parent.postMessage(WindowMessageBag("CloseAllModals"), Grocy.BaseUrl);
},
@@ -96,7 +96,7 @@ $('#save-shoppinglist-button').on('click', function(e)
Grocy.Api.Get('stock/products/' + jsonData.product_id,
function(productDetails)
{
- window.parent.postMessage(WindowMessageBag("ShowSuccessMessage", __t("Added %1$s of %2$s to the shopping list \"%3$s\"", displayAmount.toLocaleString({ minimumFractionDigits: 0, maximumFractionDigits: Grocy.UserSettings.stock_decimal_places_amounts }) + " " + __n(displayAmount, $("#qu_id option:selected").text(), $("#qu_id option:selected").attr("data-qu-name-plural")), productDetails.product.name, $("#shopping_list_id option:selected").text())), Grocy.BaseUrl);
+ window.parent.postMessage(WindowMessageBag("ShowSuccessMessage", __t("Added %1$s of %2$s to the shopping list \"%3$s\"", displayAmount.toLocaleString({ minimumFractionDigits: 0, maximumFractionDigits: Grocy.UserSettings.stock_decimal_places_amounts }) + " " + __n(displayAmount, $("#qu_id option:selected").text(), $("#qu_id option:selected").attr("data-qu-name-plural"), true), productDetails.product.name, $("#shopping_list_id option:selected").text())), Grocy.BaseUrl);
window.parent.postMessage(WindowMessageBag("ShoppingListChanged", $("#shopping_list_id").val().toString()), Grocy.BaseUrl);
window.parent.postMessage(WindowMessageBag("CloseAllModals"), Grocy.BaseUrl);
},
@@ -138,7 +138,7 @@ $('#save-shoppinglist-button').on('click', function(e)
Grocy.Api.Get('stock/products/' + jsonData.product_id,
function(productDetails)
{
- window.parent.postMessage(WindowMessageBag("ShowSuccessMessage", __t("Added %1$s of %2$s to the shopping list \"%3$s\"", displayAmount.toLocaleString({ minimumFractionDigits: 0, maximumFractionDigits: Grocy.UserSettings.stock_decimal_places_amounts }) + " " + __n(displayAmount, $("#qu_id option:selected").text(), $("#qu_id option:selected").attr("data-qu-name-plural")), productDetails.product.name, $("#shopping_list_id option:selected").text())), Grocy.BaseUrl);
+ window.parent.postMessage(WindowMessageBag("ShowSuccessMessage", __t("Added %1$s of %2$s to the shopping list \"%3$s\"", displayAmount.toLocaleString({ minimumFractionDigits: 0, maximumFractionDigits: Grocy.UserSettings.stock_decimal_places_amounts }) + " " + __n(displayAmount, $("#qu_id option:selected").text(), $("#qu_id option:selected").attr("data-qu-name-plural"), true), productDetails.product.name, $("#shopping_list_id option:selected").text())), Grocy.BaseUrl);
window.parent.postMessage(WindowMessageBag("ShoppingListChanged", $("#shopping_list_id").val().toString()), Grocy.BaseUrl);
window.parent.postMessage(WindowMessageBag("CloseAllModals"), Grocy.BaseUrl);
},
diff --git a/public/viewjs/stockentries.js b/public/viewjs/stockentries.js
index 4b3fdd6f..4a89fdd4 100644
--- a/public/viewjs/stockentries.js
+++ b/public/viewjs/stockentries.js
@@ -4,12 +4,12 @@
{ 'orderable': false, 'targets': 0 },
{ 'searchable': false, "targets": 0 },
{ 'visible': false, 'targets': 10 },
- { "type": "num", "targets": 1},
+ { "type": "num", "targets": 1 },
{ "type": "num", "targets": 3 },
{ "type": "html", "targets": 4 },
- { "type": "html-num-fmt", "targets": 7},
- { "type": "html", "targets": 8},
- { "type": "html", "targets": 9}
+ { "type": "html-num-fmt", "targets": 7 },
+ { "type": "html", "targets": 8 },
+ { "type": "html", "targets": 9 }
].concat($.fn.dataTable.defaults.columnDefs)
});
$('#stockentries-table tbody').removeClass("d-none");
@@ -67,7 +67,7 @@ $(document).on('click', '.stock-consume-button', function(e)
Grocy.Api.Get('stock/products/' + productId,
function(result)
{
- var toastMessage = __t('Removed %1$s of %2$s from stock', parseFloat(consumeAmount).toLocaleString({ minimumFractionDigits: 0, maximumFractionDigits: Grocy.UserSettings.stock_decimal_places_amounts }) + " " + __n(consumeAmount, result.quantity_unit_stock.name, result.quantity_unit_stock.name_plural), result.product.name) + '
' + __t("Undo") + '';
+ var toastMessage = __t('Removed %1$s of %2$s from stock', parseFloat(consumeAmount).toLocaleString({ minimumFractionDigits: 0, maximumFractionDigits: Grocy.UserSettings.stock_decimal_places_amounts }) + " " + __n(consumeAmount, result.quantity_unit_stock.name, result.quantity_unit_stock.name_plural, true), result.product.name) + '
' + __t("Undo") + '';
if (wasSpoiled)
{
toastMessage += " (" + __t("Spoiled") + ")";
diff --git a/public/viewjs/stockoverview.js b/public/viewjs/stockoverview.js
index 4dc03eac..54c56f78 100755
--- a/public/viewjs/stockoverview.js
+++ b/public/viewjs/stockoverview.js
@@ -145,11 +145,11 @@ $(document).on('click', '.product-consume-button', function(e)
{
if (result.product.enable_tare_weight_handling == 1)
{
- var toastMessage = __t('Removed %1$s of %2$s from stock', parseFloat(originalTotalStockAmount).toLocaleString({ minimumFractionDigits: 0, maximumFractionDigits: Grocy.UserSettings.stock_decimal_places_amounts }) + " " + __n(consumeAmount, result.quantity_unit_stock.name, result.quantity_unit_stock.name_plural), result.product.name) + '
' + __t("Undo") + '';
+ var toastMessage = __t('Removed %1$s of %2$s from stock', parseFloat(originalTotalStockAmount).toLocaleString({ minimumFractionDigits: 0, maximumFractionDigits: Grocy.UserSettings.stock_decimal_places_amounts }) + " " + __n(consumeAmount, result.quantity_unit_stock.name, result.quantity_unit_stock.name_plural, true), result.product.name) + '
' + __t("Undo") + '';
}
else
{
- var toastMessage = __t('Removed %1$s of %2$s from stock', parseFloat(consumeAmount).toLocaleString({ minimumFractionDigits: 0, maximumFractionDigits: Grocy.UserSettings.stock_decimal_places_amounts }) + " " + __n(consumeAmount, result.quantity_unit_stock.name, result.quantity_unit_stock.name_plural), result.product.name) + '
' + __t("Undo") + '';
+ var toastMessage = __t('Removed %1$s of %2$s from stock', parseFloat(consumeAmount).toLocaleString({ minimumFractionDigits: 0, maximumFractionDigits: Grocy.UserSettings.stock_decimal_places_amounts }) + " " + __n(consumeAmount, result.quantity_unit_stock.name, result.quantity_unit_stock.name_plural, true), result.product.name) + '
' + __t("Undo") + '';
}
if (wasSpoiled)
@@ -328,7 +328,7 @@ function RefreshProductRow(productId)
{
animateCSS("#product-" + productId + "-row td:not(:first)", "shake");
- $('#product-' + productId + '-qu-name').text(__n(result.stock_amount, result.quantity_unit_stock.name, result.quantity_unit_stock.name_plural));
+ $('#product-' + productId + '-qu-name').text(__n(result.stock_amount, result.quantity_unit_stock.name, result.quantity_unit_stock.name_plural, true));
$('#product-' + productId + '-amount').text(result.stock_amount);
$('#product-' + productId + '-consume-all-button').attr('data-consume-amount', result.stock_amount);
$('#product-' + productId + '-value').text(result.stock_value);
diff --git a/public/viewjs/transfer.js b/public/viewjs/transfer.js
index 74126afc..4ad149ee 100644
--- a/public/viewjs/transfer.js
+++ b/public/viewjs/transfer.js
@@ -56,11 +56,11 @@
if (productDetails.product.enable_tare_weight_handling == 1)
{
- var successMessage = __t('Transfered %1$s of %2$s from %3$s to %4$s', Math.abs(jsonForm.amount - parseFloat(productDetails.product.tare_weight)) + " " + __n(jsonForm.amount, productDetails.quantity_unit_stock.name, productDetails.quantity_unit_stock.name_plural), productDetails.product.name, $('option:selected', "#location_id_from").text(), $('option:selected', "#location_id_to").text()) + '
' + __t("Undo") + '';
+ var successMessage = __t('Transfered %1$s of %2$s from %3$s to %4$s', Math.abs(jsonForm.amount - parseFloat(productDetails.product.tare_weight)) + " " + __n(jsonForm.amount, productDetails.quantity_unit_stock.name, productDetails.quantity_unit_stock.name_plural, true), productDetails.product.name, $('option:selected', "#location_id_from").text(), $('option:selected', "#location_id_to").text()) + '
' + __t("Undo") + '';
}
else
{
- var successMessage = __t('Transfered %1$s of %2$s from %3$s to %4$s', Math.abs(jsonForm.amount) + " " + __n(jsonForm.amount, productDetails.quantity_unit_stock.name, productDetails.quantity_unit_stock.name_plural), productDetails.product.name, $('option:selected', "#location_id_from").text(), $('option:selected', "#location_id_to").text()) + '
' + __t("Undo") + '';
+ var successMessage = __t('Transfered %1$s of %2$s from %3$s to %4$s', Math.abs(jsonForm.amount) + " " + __n(jsonForm.amount, productDetails.quantity_unit_stock.name, productDetails.quantity_unit_stock.name_plural, true), productDetails.product.name, $('option:selected', "#location_id_from").text(), $('option:selected', "#location_id_to").text()) + '
' + __t("Undo") + '';
}
if (GetUriParam("embedded") !== undefined)
diff --git a/services/LocalizationService.php b/services/LocalizationService.php
index dbd5b417..16b27ae6 100644
--- a/services/LocalizationService.php
+++ b/services/LocalizationService.php
@@ -17,21 +17,21 @@ class LocalizationService
protected $Po;
- protected $PoUserStrings;
-
protected $Pot;
protected $PotMain;
protected $Translator;
+ protected $TranslatorQU;
+
private static $instanceMap = [];
public function CheckAndAddMissingTranslationToPot($text)
{
if (GROCY_MODE === 'dev')
{
- if ($this->Pot->find('', $text) === false && $this->PoUserStrings->find('', $text) === false && empty($text) === false)
+ if ($this->Pot->find('', $text) === false && empty($text) === false)
{
$translation = new Translation('', $text);
$this->PotMain[] = $translation;
@@ -69,11 +69,23 @@ class LocalizationService
return $this->Po->toJsonString();
}
- public function __n($number, $singularForm, $pluralForm)
+ public function GetPoAsJsonStringQu()
+ {
+ return $this->PoQu->toJsonString();
+ }
+
+ public function __n($number, $singularForm, $pluralForm, $isQu = false)
{
$this->CheckAndAddMissingTranslationToPot($singularForm);
- return sprintf($this->Translator->ngettext($singularForm, $pluralForm, abs(floatval($number))), $number);
+ if ($isQu)
+ {
+ return sprintf($this->TranslatorQU->ngettext($singularForm, $pluralForm, abs(floatval($number))), $number);
+ }
+ else
+ {
+ return sprintf($this->Translator->ngettext($singularForm, $pluralForm, abs(floatval($number))), $number);
+ }
}
public function __t($text, ...$placeholderValues)
@@ -140,9 +152,6 @@ class LocalizationService
}
}
- $this->PoUserStrings = new Translations();
- $this->PoUserStrings->setDomain('grocy/userstrings');
-
$this->Po = Translations::fromPoFile(__DIR__ . "/../localization/$culture/strings.po");
if (file_exists(__DIR__ . "/../localization/$culture/chore_assignment_types.po"))
@@ -185,6 +194,9 @@ class LocalizationService
$this->Po = $this->Po->mergeWith(Translations::fromPoFile(__DIR__ . "/../localization/$culture/demo_data.po"));
}
+ $this->Translator = new Translator();
+ $this->Translator->loadTranslations($this->Po);
+
$quantityUnits = null;
try
{
@@ -197,6 +209,8 @@ class LocalizationService
if ($quantityUnits !== null)
{
+ $this->PoQu = new Translations();
+
foreach ($quantityUnits as $quantityUnit)
{
$translation = new Translation('', $quantityUnit['name']);
@@ -204,13 +218,11 @@ class LocalizationService
$translation->setPlural($quantityUnit['name_plural']);
$translation->setPluralTranslations(preg_split('/\r\n|\r|\n/', $quantityUnit['plural_forms']));
- $this->PoUserStrings[] = $translation;
+ $this->PoQu[] = $translation;
}
- $this->Po = $this->Po->mergeWith($this->PoUserStrings);
- }
-
- $this->Translator = new Translator();
- $this->Translator->loadTranslations($this->Po);
+ $this->TranslatorQU = new Translator();
+ $this->TranslatorQU->loadTranslations($this->PoQu);
+ };
}
}
diff --git a/views/layout/default.blade.php b/views/layout/default.blade.php
index c0057c25..e1b1377a 100644
--- a/views/layout/default.blade.php
+++ b/views/layout/default.blade.php
@@ -95,6 +95,7 @@
Grocy.CalendarFirstDayOfWeek = '{{ GROCY_CALENDAR_FIRST_DAY_OF_WEEK }}';
Grocy.CalendarShowWeekNumbers = {{ BoolToString(GROCY_CALENDAR_SHOW_WEEK_OF_YEAR) }};
Grocy.LocalizationStrings = {!! $LocalizationStrings !!};
+ Grocy.LocalizationStringsQu = {!! $LocalizationStringsQu !!};
Grocy.FeatureFlags = {!! json_encode($featureFlags) !!};
Grocy.Webhooks = {
@if(GROCY_FEATURE_FLAG_LABEL_PRINTER && !GROCY_LABEL_PRINTER_RUN_SERVER)
diff --git a/views/locationcontentsheet.blade.php b/views/locationcontentsheet.blade.php
index 5f27ca1e..73e99125 100644
--- a/views/locationcontentsheet.blade.php
+++ b/views/locationcontentsheet.blade.php
@@ -89,7 +89,7 @@
{{ FindObjectInArrayByPropertyValue($products, 'id', $currentStockEntry->product_id)->name }}
- {{ $currentStockEntry->amount }} {{ $__n($currentStockEntry->amount, FindObjectInArrayByPropertyValue($quantityunits, 'id', FindObjectInArrayByPropertyValue($products, 'id', $currentStockEntry->product_id)->qu_id_stock)->name, FindObjectInArrayByPropertyValue($quantityunits, 'id', FindObjectInArrayByPropertyValue($products, 'id', $currentStockEntry->product_id)->qu_id_stock)->name_plural) }}
+ {{ $currentStockEntry->amount }} {{ $__n($currentStockEntry->amount, FindObjectInArrayByPropertyValue($quantityunits, 'id', FindObjectInArrayByPropertyValue($products, 'id', $currentStockEntry->product_id)->qu_id_stock)->name, FindObjectInArrayByPropertyValue($quantityunits, 'id', FindObjectInArrayByPropertyValue($products, 'id', $currentStockEntry->product_id)->qu_id_stock)->name_plural, true) }}
@if($currentStockEntry->amount_opened > 0){{ $__t('%s opened', $currentStockEntry->amount_opened) }}@endif
|
|
diff --git a/views/productform.blade.php b/views/productform.blade.php
index 749617ca..9f48bffa 100644
--- a/views/productform.blade.php
+++ b/views/productform.blade.php
@@ -717,7 +717,7 @@
@endif
- {!! $__t('This means 1 %1$s is the same as %2$s %3$s', FindObjectInArrayByPropertyValue($quantityunits, 'id', $quConversion->from_qu_id)->name, '' . $quConversion->factor . '', $__n($quConversion->factor, FindObjectInArrayByPropertyValue($quantityunits, 'id', $quConversion->to_qu_id)->name, FindObjectInArrayByPropertyValue($quantityunits, 'id', $quConversion->to_qu_id)->name_plural)) !!}
+ {!! $__t('This means 1 %1$s is the same as %2$s %3$s', FindObjectInArrayByPropertyValue($quantityunits, 'id', $quConversion->from_qu_id)->name, '' . $quConversion->factor . '', $__n($quConversion->factor, FindObjectInArrayByPropertyValue($quantityunits, 'id', $quConversion->to_qu_id)->name, FindObjectInArrayByPropertyValue($quantityunits, 'id', $quConversion->to_qu_id)->name_plural, true)) !!}
|
@endif
diff --git a/views/recipeform.blade.php b/views/recipeform.blade.php
index 27275fd6..bd2d3a1a 100644
--- a/views/recipeform.blade.php
+++ b/views/recipeform.blade.php
@@ -197,7 +197,7 @@
@else
@if($recipePosition->amount == round($recipePosition->amount)){{ round($recipePosition->amount) }}@else{{ $recipePosition->amount }}@endif
@endif
- {{ $__n($recipePosition->amount, FindObjectInArrayByPropertyValue($quantityunits, 'id', $recipePosition->qu_id)->name, FindObjectInArrayByPropertyValue($quantityunits, 'id', $recipePosition->qu_id)->name_plural) }}
+ {{ $__n($recipePosition->amount, FindObjectInArrayByPropertyValue($quantityunits, 'id', $recipePosition->qu_id)->name, FindObjectInArrayByPropertyValue($quantityunits, 'id', $recipePosition->qu_id)->name_plural, true) }}
@if(!empty($recipePosition->variable_amount))
{{ $__t('Variable amount') }}
diff --git a/views/shoppinglist.blade.php b/views/shoppinglist.blade.php
index d7e4d6f4..12206738 100644
--- a/views/shoppinglist.blade.php
+++ b/views/shoppinglist.blade.php
@@ -242,7 +242,7 @@
@endif
amount }}>
- {{ $listItem->amount }} @if(!empty($listItem->product_id)){{ $__n($listItem->amount, $listItem->qu_name, $listItem->qu_name_plural) }}@endif
+ {{ $listItem->amount }} @if(!empty($listItem->product_id)){{ $__n($listItem->amount, $listItem->qu_name, $listItem->qu_name_plural, true) }}@endif
|
@if(!empty($listItem->product_group_name)) {{ $listItem->product_group_name }} @else {{ $__t('Ungrouped') }} @endif
@@ -376,7 +376,7 @@
@if(!empty($listItem->product_id)) {{ $listItem->product_name }} @endif{!! nl2br($listItem->note) !!}
|
- {{ $listItem->amount }} @if(!empty($listItem->product_id)){{ $__n($listItem->amount, $listItem->qu_name, $listItem->qu_name_plural) }}@endif
+ {{ $listItem->amount }} @if(!empty($listItem->product_id)){{ $__n($listItem->amount, $listItem->qu_name, $listItem->qu_name_plural, true) }}@endif
|
@if(!empty($listItem->product_group_name)) {{ $listItem->product_group_name }} @else {{ $__t('Ungrouped') }} @endif
@@ -400,7 +400,7 @@
@foreach($listItems as $listItem)
- {{ $listItem->amount }} @if(!empty($listItem->product_id)){{ $__n($listItem->amount, $listItem->qu_name, $listItem->qu_name_plural) }}@endif
+ {{ $listItem->amount }} @if(!empty($listItem->product_id)){{ $__n($listItem->amount, $listItem->qu_name, $listItem->qu_name_plural, true) }}@endif
@if(!empty($listItem->product_id)) {{ $listItem->product_name }} @endif{!! nl2br($listItem->note) !!}
@endforeach
diff --git a/views/stockentries.blade.php b/views/stockentries.blade.php
index 6762b09d..e868a4f9 100644
--- a/views/stockentries.blade.php
+++ b/views/stockentries.blade.php
@@ -233,7 +233,7 @@
|
{{ $stockEntry->amount }} {{ $__n($stockEntry->amount, FindObjectInArrayByPropertyValue($quantityunits, 'id', FindObjectInArrayByPropertyValue($products, 'id', $stockEntry->product_id)->qu_id_stock)->name, FindObjectInArrayByPropertyValue($quantityunits, 'id', FindObjectInArrayByPropertyValue($products, 'id', $stockEntry->product_id)->qu_id_stock)->name_plural) }}
+ class="locale-number locale-number-quantity-amount">{{ $stockEntry->amount }} {{ $__n($stockEntry->amount, FindObjectInArrayByPropertyValue($quantityunits, 'id', FindObjectInArrayByPropertyValue($products, 'id', $stockEntry->product_id)->qu_id_stock)->name, FindObjectInArrayByPropertyValue($quantityunits, 'id', FindObjectInArrayByPropertyValue($products, 'id', $stockEntry->product_id)->qu_id_stock)->name_plural, true) }}
@if($stockEntry->open == 1){{ $__t('Opened') }}@endif
|
diff --git a/views/stockjournal.blade.php b/views/stockjournal.blade.php
index 503e9077..4191674e 100644
--- a/views/stockjournal.blade.php
+++ b/views/stockjournal.blade.php
@@ -174,7 +174,7 @@
@endif
- {{ $stockLogEntry->amount }} {{ $__n($stockLogEntry->amount, $stockLogEntry->qu_name, $stockLogEntry->qu_name_plural) }}
+ {{ $stockLogEntry->amount }} {{ $__n($stockLogEntry->amount, $stockLogEntry->qu_name, $stockLogEntry->qu_name_plural, true) }}
|
{{ $stockLogEntry->row_created_timestamp }}
diff --git a/views/stockjournalsummary.blade.php b/views/stockjournalsummary.blade.php
index 3c6d6ef1..4cf4c44c 100644
--- a/views/stockjournalsummary.blade.php
+++ b/views/stockjournalsummary.blade.php
@@ -120,7 +120,7 @@
{{ $journalEntry->user_display_name }}
|
- {{ $journalEntry->amount }} {{ $__n($journalEntry->amount, $journalEntry->qu_name, $journalEntry->qu_name_plural) }}
+ {{ $journalEntry->amount }} {{ $__n($journalEntry->amount, $journalEntry->qu_name, $journalEntry->qu_name_plural, true) }}
|
@endforeach
diff --git a/views/stockoverview.blade.php b/views/stockoverview.blade.php
index 6ad64ef3..5423cf3d 100755
--- a/views/stockoverview.blade.php
+++ b/views/stockoverview.blade.php
@@ -329,7 +329,7 @@
@if($currentStockEntry->is_aggregated_amount == 1)
{{ $currentStockEntry->amount_aggregated }} {{ $__n($currentStockEntry->amount_aggregated, $currentStockEntry->qu_unit_name, $currentStockEntry->qu_unit_name_plural) }}
+ class="locale-number locale-number-quantity-amount">{{ $currentStockEntry->amount_aggregated }} {{ $__n($currentStockEntry->amount_aggregated, $currentStockEntry->qu_unit_name, $currentStockEntry->qu_unit_name_plural, true) }}
@if($currentStockEntry->amount_opened_aggregated > 0)
{{ $__t('%s opened', $currentStockEntry->amount_opened_aggregated) }}@endif