Files
objecttothis 6db3dde491 Bugfix tax names (#4677)
bugfix(items, validation): reject unsafe tax names and fix payments temp table collision

- Add unicode_alpha_numeric_punct rule (OSPOSRules) to allow accented/CJK
  chars in text fields while blocking HTML-unsafe chars (<, >) as
  defense-in-depth against injection
- Items controller: extract validateItemFields/validateBulkUpdateFields,
  validate tax_names on save and bulk update using new rule; add shared
  validateFields helper in Secure_Controller to DRY up validation +
  JSON error response
- Escape tax_group output in sales/quote.php and receipt_email.php views
  to harden output encoding at render time
- Rename sales_payments_temp -> sales_report_payments_temp (Summary_report)
  and -> sales_search_payments_temp (Sale model) to avoid name collision
  between concurrently-created temp tables
- AGENTS.md: document alignment rule for => columns when inserting new
  language keys

Tests:
- Add ItemsControllerTest covering postSave/bulkupdate tax_names validation
- Reject <, > in tax_names on /items/save and /items/bulkupdate
- Verify unicode and apostrophe-containing tax names are accepted
- Cover CSV import helpers: header generation (basic, multiple locations,
  attributes), stock-location/attribute header builders, get_csv_file
  parsing (plain, BOM-prefixed, multi-row)
- Validate required-header detection for import templates
- Remove outdated tax name test from SalesControllerTest
- Simplify Database class references in SalesControllerTest

i18n:
- Add tax_name_invalid translation to Items.php for 20+ locales, inserted
  alphabetically after tax_category in each file
- Normalize quote style in ar-EG/Items.php to single quotes
- Add ka/Items.php Georgian locale scaffold

Signed-off-by: objecttothis <17935339+objecttothis@users.noreply.github.com>
2026-09-01 10:59:29 +04:00

125 lines
11 KiB
PHP
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
return [
'add_minus' => 'Добавить/убрать товар.',
'allow_alt_description' => 'Разрешить альтернативные описания',
'amount_entry' => 'Ввод количества',
'bulk_edit' => 'Массовое редактирование',
'buy_price_required' => 'Цена покупки - обязательное поле.',
'cannot_be_deleted' => 'Не удалось удалить выбраннй(ые) товар(ы), так как у одного или нескольких выбранных товаров есть продажи.',
'cannot_find_item' => 'Товар не найден.',
'categories' => '',
'category' => 'Категория',
'category_new' => '',
'category_required' => 'Категория - обязательное поле.',
'change_all_to_allow_alt_desc' => 'Разрешить альтернативное описание для всех.',
'change_all_to_not_allow_allow_desc' => 'Не разрешать альтернативные описания для всех.',
'change_all_to_serialized' => 'Выбрать все',
'change_all_to_unserialized' => 'Снять выделение со всех',
'change_image' => 'Изменить изображение',
'confirm_bulk_edit' => 'Вы уверены, что хотите редактировать выбранные товары?',
'confirm_bulk_edit_wipe_taxes' => 'Вся информация о налогах на товар будет изменена.',
'confirm_delete' => 'Вы уверены, что хотите удалить выбранные товары?',
'confirm_restore' => 'Вы уверены, что хотите восстановить выбранные товары?',
'cost_price' => 'Оптовая цена',
'cost_price_number' => 'Оптовая цена должна быть числом.',
'cost_price_required' => 'Оптовая цена - обязательное поле.',
'count' => 'Обновление запасов',
'csv_import_failed' => 'Ошибка импорта CSV',
'csv_import_invalid_location' => '',
'csv_import_nodata_wrongformat' => 'Загруженный файл CSV не содержит данных или имеет неправильный формат.',
'csv_import_partially_failed' => 'В строке (строках) произошло {0} ошибок импорта: {1}. Ничего не было импортировано.',
'csv_import_success' => 'Товар успешно импортирован из CSV.',
'current_quantity' => 'Текущее количество',
'default_pack_name' => 'Каждый',
'description' => 'Описание',
'details_count' => 'Сведения о запасах',
'do_nothing' => 'Ничего не делать',
'edit' => '',
'edit_fields_you_want_to_update' => 'Отредактируйте нужные поля у выбранных товаров.',
'edit_multiple_items' => 'Редактирование нескольких товаров',
'empty_upc_items' => 'Штрих-код товара(ов) пуст',
'error_adding_updating' => 'Ошибка при добавлении/обновлении товара',
'error_updating_multiple' => 'Ошибка при обновлении товаров',
'generate_barcodes' => 'Генерация штрих-кодов',
'hsn_code' => 'Согласованная система номенклатуры',
'image' => 'Изображение',
'import_items_csv' => 'Импорт товаров из CSV',
'info_provided_by' => 'Информация предоставлена',
'inventory' => 'Запасы',
'inventory_CSV_import_quantity' => 'Импортированое количество из CSV',
'inventory_comments' => 'Комментарии',
'inventory_data_tracking' => 'Отслеживание запасов',
'inventory_date' => 'Дата',
'inventory_employee' => 'Сотрудник',
'inventory_in_out_quantity' => 'Количество (Приход / Уход)',
'inventory_remarks' => 'Пометки',
'is_deleted' => 'Удаленный',
'is_printed' => '',
'is_serialized' => 'Товар имеет серийный номер',
'item' => 'Товар',
'item_id' => '',
'item_number' => 'Штрих-код',
'item_number_duplicate' => 'Товар с таким номером уже присутствует в базе данных.',
'item_number_invalid' => 'Номер товара содержит недопустимые символы.',
'kit' => 'Комплект',
'location' => 'Расположение',
'low_inventory_items' => 'Товары не в наличии',
'low_sell_item' => 'Товар с низким уровнем продаж',
'manually_editing_of_quantity' => 'Ручное редактирование количества',
'markup' => '',
'name' => 'Название товара',
'name_required' => 'Название товара - обязательно для заполнения.',
'new' => 'Новый товар',
'no_description_items' => 'Нет описания товаров',
'no_items_to_display' => 'Нет товаров для отображения.',
'none' => 'Нет',
'none_selected' => 'Вы не выбрали ни одного товара для редактирования',
'nonstock' => 'Нет в наличии',
'number_information' => 'Номер товара',
'number_required' => 'Штрихкод - обязательное поле для заполнения.',
'one_or_multiple' => 'товар(ов)',
'pack_name' => 'Название упаковки',
'qty_per_pack' => 'Количество в упаковке',
'quantity' => 'Количество',
'quantity_number' => 'Количество должно быть числом.',
'quantity_required' => 'Количество - обязательное поле для заполнения.',
'receiving_quantity' => 'Количество закупок',
'remove_image' => 'Удалить изображение',
'reorder_level' => 'Уровень повторного заказа',
'reorder_level_number' => 'Уровень повторного заказа должно быть числом.',
'reorder_level_required' => 'Уровень повторного заказа - обязательное поле для заполнения.',
'retrive_item_info' => 'Информация о получении товара',
'sales_tax_1' => 'Налог на продажу',
'sales_tax_2' => 'Налог на продажу 2',
'search_attributes' => 'Поиск атрибутов',
'select_image' => 'Выбрать изображение',
'serialized_items' => 'Выбранные товары',
'standard' => 'Стандарт',
'stock' => 'В наличии',
'stock_location' => 'Расположение запасов',
'stock_type' => 'Наличие',
'successful_adding' => 'Вы успешно добавили товар',
'successful_bulk_edit' => 'Вы успешно обновили выбранный товар(ы)',
'successful_deleted' => 'Успешно удалено',
'successful_updating' => 'Товар успешно обновлен',
'supplier' => 'Поставщик',
'tax_1' => 'Налог 1',
'tax_2' => 'Налог 2',
'tax_3' => '',
'tax_category' => 'Категория налога',
'tax_name_invalid' => 'Название налога содержит недопустимые символы.',
'tax_percent' => 'процент налога',
'tax_percent_number' => 'Налоговый процент должен быть числом',
'tax_percent_required' => 'Налоговый процент - обязательно для заполнения.',
'tax_percents' => 'Налоговый процент',
'temp' => 'Временный',
'type' => 'Тип товара',
'unit_price' => 'Розничная цена',
'unit_price_number' => 'Розничная цена должна быть числом.',
'unit_price_required' => 'Розничная цена - обязательное поле для заполнения.',
'upc_database' => 'База данных штрих-кодов',
'update' => 'Обновление товара',
'use_inventory_menu' => 'Использовать меню запасов',
];