Files
opensourcepos/app/Language/ckb/Config.php
T
184918d914 fix(security): handle special characters in .env key values and improve insertion logic (#4656)
* fix(security): handle special characters in `.env` key values and improve insertion logic

- Escape backslashes and dollar signs in `applyEnvKeyReplacement` to prevent unintended value corruption.
- Ensure new keys are inserted after `encryption.key` for better organization and manageability.
- Add explicit cast to int to prevent wrong concatenation operator warning.

Signed-off-by: objecttothis <17935339+objecttothis@users.noreply.github.com>

* fix(security): handle null return in `applyEnvKeyReplacement` and ensure proper `.env` updates

- Update `applyEnvKeyReplacement` to return `null` on failure, improving error handling.
- Adjust calls to `atomicWriteFile` with updated content to prevent unintended behavior.

Signed-off-by: objecttothis <17935339+objecttothis@users.noreply.github.com>

* fix(security): improve error logging and exception messages in file locking

- Add detailed logging for file open and locking errors in `security_helper`.
- Remove unused `helper` and `checkThrottleEncryption` calls from `Events` for cleanup.

Signed-off-by: objecttothis <17935339+objecttothis@users.noreply.github.com>

* fix(security): improve atomic file write and handle encryption key placement

- Throw `RandomException` for better error reporting in `atomicWriteFile`.
- Simplify Windows-specific `rename()` fallback logic.
- Fix `encryption.key` assignment order to ensure consistency in `.env` updates.

Signed-off-by: objecttothis <17935339+objecttothis@users.noreply.github.com>

* fix(security): improve `.env` file handling and add unit tests for helper functions

- Suppress warnings in `file_get_contents` to prevent unnecessary error logs.
- Update `applyEnvKeyReplacement` to use `preg_replace_callback` for better safety.
- Add comprehensive unit tests for `security_helper` functions to ensure `.env` updates and key management work as expected.

Signed-off-by: objecttothis <17935339+objecttothis@users.noreply.github.com>

* fix(security): enhance `.env` update logic and add robust exception handling

- Add `RandomException` to improve error reporting in encryption key management.
- Introduce environment file locking for safer `.env` updates.
- Ensure `applyEnvKeyReplacement` properly handles and inserts old key comments.
- Replace direct file writes with `atomicWriteFile` for consistency.

Signed-off-by: objecttothis <17935339+objecttothis@users.noreply.github.com>

* fix(security): refactor `.env` file initialization and encryption key handling

- Introduce `initializeEnvFile` for reusable `.env` setup logic.
- Add `backupEnvFile` and `writeNewEncryptionKey` for robust key management with backups.
- Simplify and clean up redundant `.env` handling code paths.

Signed-off-by: objecttothis <17935339+objecttothis@users.noreply.github.com>

* fix(security): clarify `checkEncryption` docblock return value description

Signed-off-by: objecttothis <17935339+objecttothis@users.noreply.github.com>

* fix(security): escape backslashes and dollar signs in `applyEnvKeyReplacement`

- Ensure `applyEnvKeyReplacement` properly escapes special characters when inserting or appending `.env` keys.
- Add new unit tests to validate correct handling of backslashes and dollar signs.

Signed-off-by: objecttothis <17935339+objecttothis@users.noreply.github.com>

* fix(i18n): add localized error messages and improve error reporting in `security_helper`

- Add missing translations for error messages across multiple language files.
- Update `security_helper` to use localized exception messages with placeholders.

Signed-off-by: objecttothis <17935339+objecttothis@users.noreply.github.com>

* Redesign encryption/throttle key provisioning as read-only runtime

- checkEncryption()/checkThrottleEncryption() are now read-only guards that
  throw when no valid key is provisioned, instead of writing .env at
  request time.
- Add rotateEncryptionKey() and provisionThrottleKey() for explicit,
  idempotent provisioning.
- Add php spark env:provision (app/Commands/EnvProvision.php) so Docker can
  provision keys once at container startup before any request.
- Add app/Libraries/CI3SecretConverter.php shared CI3->CI4 secret converter
  (AES-128-CBC decrypt + CI4 re-encrypt/verify/save) used by both the
  interactive migration and the docker startup path.
- Refactor convertToCI4 migration to use the shared converter.
- Persist .env in a named volume and run spark env:provision on boot; stop
  baking .env into the shipped image.
- Add guard/rotation/throttle + converter tests; clean up orphaned
  msg_pwd_required language keys across all locales.

* fix: save CI4 ciphertext in env:provision and bind-mount a .env file

Addresses CodeRabbit review on PR #4656:

- env:provision CI3 branch was persisting *plaintext* secrets (saveAll($plain))
  instead of the CI4 ciphertext, unlike the ConvertToCI4 migration. Now
  encrypts with encryptAll(), verifies the round trip, and saves the ciphertext.
- The ospos_env named volume mounted at /app/.env made .env a directory, so
  atomicWriteFile's rename() failed and spark env:provision could not start apache.
  Switch to a bind mount of a host file (./.env) which persists and stays a file.
- Add a regression test asserting the command persists ciphertext (not plaintext).

* chore: trim redundant docblocks in EnvProvision and provision throttle.key in CI

Follow up on @objecttothis review comments:
- app/Commands/EnvProvision.php: remove the boilerplate docblocks the
  property names already convey (group/name/usage/description, run()),
  the two inline step comments, the anyNonEmpty() param docblock, and the
  legacySecretsPresent() docblock. Keeps the class-level docblock since it
  is the only place that states the read-only runtime design + the
  never-persist-plaintext invariant.
- .github/workflows/phpunit.yml: provision a per-run throttle.key the same
  way the encryption key is already provisioned. The PR makes
  checkThrottleEncryption() a read-only guard that throws when
  env('throttle.key') is unset; CI only started exporting ENCRYPTION_KEY,
  so every test that goes through the Throttle filter (7 ThrottleTest
  cases + 4 LoginTest cases) failed with
  "No throttle key is provisioned. Run `php spark env:provision`".
  Writing `throttle.key=<KEY>` into .env matches what
  `php spark env:provision` does on a real container start.

* fix(ci): write throttle.key into .env instead of exporting an OS env var

The previous attempt exported throttle.key via GITHUB_ENV, but CodeIgniter's
env() helper resolves in the order $_ENV[$key] ?? $_SERVER[$key] ?? getenv($key),
and DotEnv populates $_ENV['throttle.key'] from the .env file first. Because the
.env (copied from .env.example) ships with the empty placeholder throttle.key='',
that $_ENV entry exists as '' and short-circuits the ?? chain before getenv()
is reached — so the OS env var was never consulted and every Throttle/Login test
still threw 'No throttle key is provisioned'.

Write the per-run key into the .env file itself (sed-replacing the empty
placeholder), which is exactly what `php spark env:provision` does in
production and is the single source env() actually reads from.

Verify the replacement happened (grep -Eq '^throttle\.key=.') so a future change
to the placeholder format fails the run loudly instead of silently breaking
the 11 throttle-dependent tests.

* fix(security): restore CI3->CI4 auto-provisioning gated by .env writability

checkEncryption()/checkThrottleEncryption() again provision the keys
inline when .env is writable (empty key -> generate; short key -> decrypt,
rotate, re-encrypt, verify, persist legacy CI3 secrets). When .env is not
writable they assume the key was provisioned externally (e.g. docker
env:provision) and throw. Update helper tests to match and correct the
EnvProvision docblock that claimed the runtime was strictly read-only.

* test(security): make short-key conversion branch injectable and test it

checkEncryption() now accepts an optional CI3SecretConverter so the
CI3->CI4 conversion branch can be exercised in unit tests without a
database. Adds testCheckEncryptionConvertsCi3ShortKeyWhenEnvWritable
which seeds CI3-era ciphertexts via a fake Appconfig model and asserts
the key is rotated and the payload verifies back to the original
plaintext.

* fix(security): abort on backup/read/saveAll failure to avoid data loss

Three related data-integrity fixes:

- backupEnvFile() now returns true/false based on whether the backup
  actually exists and is readable. rotateEncryptionKey() aborts before
  destroying the key when the backup could not be written to disk.

- rotateEncryptionKey() and provisionThrottleKey() throw
  RuntimeException(Error.unable_to_read_env_file) when the .env read
  fails, instead of silently replacing the whole file with an empty
  string. This prevents a permission error from wiping all keys.

- checkEncryption() and EnvProvision::run() now both roll back to the
  backup with abortEncryptionConversion() when the post-rotation
  saveAll() throws, matching the migration path (which already did this).
  A failing fake Appconfig is used to exercise this in the new
  testCheckEncryptionRollsBackWhenSaveAllFails test.

* fix(ci): skip comment job in deploy-pr.yml when prepare was not run

The comment job had if: always(), so it ran even when the prepare job
was skipped (e.g. review was not approved). With PR_NUMBER empty the gh
api call posted to issues//comments, received a 404, and the entire run
showed up as failure. Guard the job with
needs.prepare.result == 'success' so it only runs when PR_NUMBER is valid.

* address coderabbit open items: placeholder guards, message neutrality, ar-EG alignment

- backupEnvFile(): fail when mkdir() or either chmod() fails, so the
  pre-rotation backup is actually persisted before the key is replaced
- email/message config views: only show the 'already set' placeholder when
  the secret is actually present (prevented false positives on fresh installs)
- Error.unable_to_create_env_file / .unable_to_read_env_file (en + en-GB):
  use key-neutral wording since both keys are provisioned with the same keys
- ar-EG/Error.php: align all => arrows on the longest key

Item 7 (filesystem test isolation) is a larger refactor — the tests are
serial on CI and tearDown() restores state per test. Left for follow-up.

* test(security): isolate helper FS tests via Config\SecurityEnv

Introduce Config\SecurityEnv holding envPath/backupPath/lockPath so the
security helper reads its target paths from shared configuration instead of
hardcoded ROOTPATH/WRITEPATH literals. security_helperTest.php now redirects
all three to a unique per-run sandbox under sys_get_temp_dir() and tears it
down in tearDown(), so the suite no longer reads/writes the repository's real
.env and is safe to run in parallel.

No helper signature changes; production callers unaffected.

Addresses CodeRabbit item 7 (issue #4700).

Co-Authored-By: opencode <bot@opencode.ai>

* fix(security): run key-conversion as one locked transaction

Address CodeRabbit Major findings from the 4th re-review of the env
helper and its callers:

1. Hold .env.lock for the entire CI3 -> CI4 conversion transaction
   (backup -> rotate -> re-encrypt -> verify -> persist -> cleanup) so a
   concurrent worker cannot interleave a key write between the rotation
   and the ciphertext save. Split rotateEncryptionKey into a lock-free
   core (rotateEncryptionKeyUnlock) plus the existing lock wrapper and a
   new rotateEncryptionKeyTransaction that owns the lock across the full
   unit and performs both the in-lock rollback (abortEncryptionConversion)
   and the in-lock backup removal on success.

2. Treat the legacy value '0' as non-empty data so key rotation still
   persists the re-encrypted ciphertext when '0' is the only stored
   secret (array_filter would have dropped it and skipped saveAll).

3. Wrap the post-rotation re-encrypt/verify/saveAll sequence in a
   catch (Throwable) across all three call-sites so CI4
   EncryptionException, ReflectionException from batch_save, a failed
   round-trip verify, and any other failure all roll the .env key back
   to the pre-rotation state.

4. In Docker Compose, use long-syntax bind with create_host_path: false
   and document in INSTALL.md that the host .env must be a regular file
   (a missing one is no longer auto-created as a directory, and the
   mount now rejects a missing source on Compose implementations that
   support the flag).

Files touched: app/Helpers/security_helper.php, app/Commands/EnvProvision.php,
app/Database/Migrations/20220127000000_convertToCI4.php, docker-compose.yml,
INSTALL.md. All 4 existing helper tests still pass via CI.

* fix(security): make abortEncryptionConversion fail loudly on restore failure

The rollback path restored the .env backup with a suppressed
file_put_contents() and an unchecked file_get_contents(). If the restore
failed after the key had already been rotated, .env was left holding the new
CI4 key while the DB still held CI3-era ciphertext, so the data became
undecryptable after the next restart.

Now the backup read is checked for false and the restore goes through the
existing atomicWriteFile() helper; either failure throws so the error is
surfaced instead of silently corrupting the config. Adds a regression test
that forces an unreadable backup and asserts the throw plus that .env is
left untouched.

* fix(security): guard abortEncryptionConversion backup read before touching it

Validate the backup is a regular readable file (is_file/is_readable) before
reading it, so a missing/malformed backup fails loudly instead of emitting a
file_get_contents() warning. The unreadable-backup regression test now
exercises this guard rather than relying on a promoted warning.

---------

Signed-off-by: objecttothis <17935339+objecttothis@users.noreply.github.com>
Co-authored-by: jekkos <jeroen.peelaerts@gmail.com>
Co-authored-by: jekkos <jekkos@users.noreply.github.com>
Co-authored-by: opencode <bot@opencode.ai>
2026-09-21 17:35:45 +02:00

335 lines
32 KiB
PHP
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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 [
'address' => 'ناونیشانی کۆمپانیا',
'address_required' => 'ناونیشانی کۆمپانیا خانەیەکی پێویستە.',
'all_set' => 'هەموو ڕێگەپێدانەکانی فایلەکان بە دروستی دانراون!',
'allow_duplicate_barcodes' => 'ڕێگە بە لەبەرگرتنەوەی باڕکۆدەکان بدە',
'apostrophe' => 'وێرگوڵ',
'backup_button' => 'پاڵپشت',
'backup_database' => 'بنکەدراوەی پاڵپشت',
'barcode' => 'باڕکۆد',
'barcode_company' => 'ناوی کۆمپانیا',
'barcode_configuration' => 'داڕشتنی باڕکۆد',
'barcode_content' => 'ناوەڕۆکی باڕکۆد',
'barcode_first_row' => 'ڕیزی ١',
'barcode_font' => 'فۆنت',
'barcode_formats' => 'فۆڕماتە پێدراوەکان',
'barcode_generate_if_empty' => 'ئەگەر بەتاڵ بوو دروستی بکە.',
'barcode_height' => 'بەرزی (پیکسڵ)',
'barcode_id' => 'ناسنامە/ناوی ئایتم',
'barcode_info' => 'زانیاریی داڕشتنی باڕکۆد',
'barcode_layout' => 'کڵێشەی باڕکۆد',
'barcode_name' => 'ناو',
'barcode_number' => 'باڕکۆد',
'barcode_number_in_row' => 'ژمارە لە ڕیزدا',
'barcode_page_cellspacing' => 'دووری خانەکانی لاپەڕە پیشان بدە.',
'barcode_page_width' => 'پانایی لاپەڕە پیشان بدە',
'barcode_price' => 'نرخ',
'barcode_second_row' => 'ڕیزی ٢',
'barcode_third_row' => 'ڕیزی ٣',
'barcode_tooltip' => 'ئاگاداری: ئەم تایبەتمەندییە دەتوانێت ببێتە هۆی هاوردەکردن یان دروستکردنی ئایتمی لەبەرگیراو. ئەگەر بارکۆدی لەبەرگیراوت ناوێت بەکاری مەهێنە.',
'barcode_type' => 'جۆری باڕکۆد',
'barcode_width' => 'پانی (پیکسڵ)',
'bottom' => 'ژێرەوە',
'cash_button' => '',
'cash_button_1' => '',
'cash_button_2' => '',
'cash_button_3' => '',
'cash_button_4' => '',
'cash_button_5' => '',
'cash_button_6' => '',
'cash_decimals' => 'خانەی دەیانی نەختینەیی',
'cash_decimals_tooltip' => 'ئەگەر دەیانیی نەختینەیی و دەیانیی دراو وەک یەک بن ئەوا هیچ گەورەکردنێکی نەختینەیی دەستپێناکات، مەگەر گەورەکردنی نەختینە لەسەر نیوەی پێنج دانرابێت.',
'cash_rounding' => 'گەورەکردنی نەختینەیی',
'category_dropdown' => 'پۆلێنەکە وەک درۆپداون نیشان بدە',
'center' => 'ناوەند',
'change_apperance_tooltip' => '',
'comma' => 'کۆما',
'company' => 'ناوی کۆمپانیا',
'company_avatar' => '',
'company_change_image' => 'وێنەکە بگۆڕە',
'company_logo' => 'لۆگۆی کۆمپانیا',
'company_remove_image' => 'وێنەکە لابەرە',
'company_required' => 'ناوی کۆمپانیا خانەیەکی پێویستە',
'company_select_image' => 'وێنە هەڵبژێرە',
'company_website_url' => 'ماڵپەڕی کۆمپانیا یوئارئێلێکی (http://...) دروست نییە.',
'country_codes' => 'کۆدی وڵات',
'country_codes_tooltip' => 'لیستی ناوی وڵاتان کە بە کۆما جیاکراونەتەوە بۆ گەڕان.',
'currency_code' => 'کۆدی دراو',
'currency_decimals' => 'دەیانیی دراو',
'currency_symbol' => '‎هێمای دراو',
'current_employee_only' => '',
'customer_reward' => 'پاداشت',
'customer_reward_duplicate' => 'پاداشت دەبێت بێهاوتا بێت.',
'customer_reward_enable' => 'پاداشتی کڕیار چالاک بکە',
'customer_reward_invalid_chars' => "پاداشت ناتوانێت '_' لەخۆبگرێت",
'customer_reward_required' => 'پاداشت خانەیەکی پێویستە',
'customer_sales_tax_support' => '',
'date_or_time_format' => 'فلتەری بەروار و کات',
'datetimeformat' => 'فۆڕماتی بەروار و کات',
'decimal_point' => 'خاڵی دەیانیی',
'default_barcode_font_size_number' => 'بارکۆدی بنەڕەتیی قەبارەی فۆنت دەبێت ژمارە بێت.',
'default_barcode_font_size_required' => 'بارکۆدی بنەڕەتیی قەبارەی فۆنت خانەیەکی پێویستە.',
'default_barcode_height_number' => 'بارکۆدی بنەڕەتیی بەرزی دەبێت ژمارە بێت.',
'default_barcode_height_required' => 'بارکۆدی بنەڕەتیی بەرزی خانەیەکی پێویستە.',
'default_barcode_num_in_row_number' => 'ژمارەی بارکۆدی بنەڕەتی لە ڕیزدا دەبێت ژمارە بێت.',
'default_barcode_num_in_row_required' => 'ژمارەی بارکۆدی بنەڕەتی لە ڕیزدا خانەیەکی پێویستە.',
'default_barcode_page_cellspacing_number' => 'بارکۆدی بنەڕەتیی دووری خانەکانی لاپەڕە دەبێت ژمارە بێت.',
'default_barcode_page_cellspacing_required' => 'بارکۆدی بنەڕەتیی دووری خانەکانی لاپەڕە خانەیەکی پێویستە.',
'default_barcode_page_width_number' => 'بارکۆدی بنەڕەتیی پانی لاپەڕە دەبێت ژمارە بێت.',
'default_barcode_page_width_required' => 'بارکۆدی بنەڕەتیی پانی لاپەڕە خانەیەکی پێویستە.',
'default_barcode_width_number' => 'بارکۆدی بنەڕەتیی پانی دەبێت ژمارە بێت.',
'default_barcode_width_required' => 'بارکۆدی بنەڕەتیی پانی خانەیەکی پێویستە.',
'default_item_columns' => 'ستوونی ئایتمی بینراوی بنەڕەتی',
'default_origin_tax_code' => 'کۆدی باجی ئەسڵی بنەڕەتیی',
'default_receivings_discount' => 'داشکاندنی بنەڕەتیی وەرگیراوەکان',
'default_receivings_discount_number' => 'داشکاندنی بنەڕەتیی وەرگیراوەکان دەبێت ژمارە بێت.',
'default_receivings_discount_required' => 'داشکاندنی بنەڕەتیی وەرگیراوەکان خانەیەکی پێویستە.',
'default_sales_discount' => 'داشکاندنی بنەڕەتیی فرۆشتن',
'default_sales_discount_number' => 'داشکاندنی بنەڕەتیی فرۆشتن دەبێت ژمارە بێت.',
'default_sales_discount_required' => 'داشکاندنی بنەڕەتیی فرۆشتن خانەیەکی پێویستە.',
'default_tax_category' => 'پۆلێنی باجی بنەڕەتی',
'default_tax_code' => 'کۆدی باجی بنەڕەتی',
'default_tax_jurisdiction' => 'دەسەڵاتی دادوەری باجی بنەڕەتی',
'default_tax_name_number' => 'ناوی باجی بنەڕەتی دەبێت دەقێک بێت.',
'default_tax_name_required' => 'ناوی باجی بنەڕەتی خانەیەکی پێویستە.',
'default_tax_rate' => 'ڕێژەی باجی بنەڕەتی %',
'default_tax_rate_1' => 'ڕێژەی باجی ١',
'default_tax_rate_2' => 'ڕێژەی باجی ٢',
'default_tax_rate_3' => '',
'default_tax_rate_number' => 'ڕێژەی باجی بنەڕەتی دەبێت ژمارە بێت.',
'default_tax_rate_required' => 'ڕێژەی باجی بنەڕەتی خانەیەکی پێویستە.',
'derive_sale_quantity' => 'ڕێگە بدە بە بڕی فرۆشتنی وەرگیراو',
'derive_sale_quantity_tooltip' => 'ئەگەر پشکنین بکرێت ئەوا جۆرێکی نوێی ئایتم دابین دەکرێت بۆ ئەو ئایتمانەی کە بە بڕی درێژکراوە داواکراون',
'dinner_table' => 'مێز',
'dinner_table_duplicate' => 'مێز دەبێت بێهاوتا بێت.',
'dinner_table_enable' => 'مێزەکانی نانی ئێوارە چالاک بکە',
'dinner_table_invalid_chars' => "ناوی مێز ناتوانێت '_' لەخۆبگرێت.",
'dinner_table_required' => 'مێز خانەیەکی پێویستە.',
'dot' => 'دۆت',
'email' => 'ئیمەیڵ',
'email_configuration' => 'ڕێکخستنی ئیمەیڵ',
'email_mailpath' => 'ڕێگای چوونە سەر بەرنامەی سێندمەیڵ',
'email_protocol' => 'پڕۆتۆکۆڵ',
'email_receipt_check_behaviour' => 'خانەی وەرگرتنی ئیمەیڵ',
'email_receipt_check_behaviour_always' => 'هەمیشە هەڵبژێردراوە',
'email_receipt_check_behaviour_last' => 'کۆتا هەڵبژاردنت بیر بێت',
'email_receipt_check_behaviour_never' => 'هەرگیز هەڵنەبژێردراوە',
'email_smtp_crypto' => 'بەشفرەکردنی پڕۆتۆکۆڵی SMTP',
'email_smtp_host' => 'سێرڤەری SMTP',
'email_smtp_pass' => 'وشەی نهێنی SMTP',
'email_smtp_port' => 'پۆرتی SMTP',
'email_smtp_timeout' => 'کاتی شکستی SMTP (چرکە)',
'email_smtp_user' => 'ناوی بەکارهێنەری SMTP',
'enable_avatar' => '',
'enable_avatar_tooltip' => '',
'enable_dropdown_tooltip' => '',
'enable_new_look' => '',
'enable_right_bar' => '',
'enable_right_bar_tooltip' => '',
'enforce_privacy' => 'پاراستنی نهێنی جێبەجێ بکە',
'enforce_privacy_tooltip' => 'پاراستنی نهێنی کڕیاران لە ڕێگەی جێبەجێکردنی تێکەڵکردنی داتاکان لە ئەگەری سڕانەوەی داتاکانیان',
'fax' => 'فاکس',
'file_perm' => 'کێشە لە ڕێگەپێدانەکانی فایل هەیە. تکایە ئەم پەڕەیە چاک بکەوە و دووبارە باری بکەوە.',
'financial_year' => 'دەستپێکردنی ساڵی دارایی',
'financial_year_apr' => '١ی نیسان',
'financial_year_aug' => '١ی ئاب',
'financial_year_dec' => '١ی کانوونی یەکەم',
'financial_year_feb' => '١ی شوبات',
'financial_year_jan' => '١ی کانوونی دووەم',
'financial_year_jul' => '١ی تەمووز',
'financial_year_jun' => '١ی حوزەیران',
'financial_year_mar' => '١ی ئازار',
'financial_year_may' => '١ی ئایار',
'financial_year_nov' => '١ی تشرینی دووەم',
'financial_year_oct' => '١ی تشرینی یەکەم',
'financial_year_sep' => '١ی ئەیلوول',
'floating_labels' => 'لەیبڵە هەڵفڕیوەکان',
'gcaptcha_enable' => 'پەڕەی چوونەژوورەوەی ڕیکاپچا',
'gcaptcha_secret_key' => 'کلیلی نهێنی ڕیکاپچا',
'gcaptcha_secret_key_required' => 'خانەی کلیلی نهێنی ڕیکاپچا پێویستە',
'gcaptcha_site_key' => 'کلیلی سایتی ڕیکاپچا',
'gcaptcha_site_key_required' => 'خانەی کلیلی سایتی ڕیکاپچا پێویستە',
'gcaptcha_tooltip' => 'لاپەڕەی چوونەژوورەوە لەڕێی گوگڵ ڕیکاپچا بپارێزە، کرتە لە ئایکۆنەکە بکە بۆ جووتە کلیلی ئای پی ئەی.',
'general' => 'گشتی',
'general_configuration' => 'ڕێکخستنی گشتی',
'giftcard_number' => 'ژمارەی کارتی دیاری',
'giftcard_random' => 'دروستکردنی هەڕەمەکی',
'giftcard_series' => 'دروستکردن بە زنجیرە',
'image_allowed_file_types' => 'جۆری فایلە ڕێگەپێدراوەکان',
'image_max_height_tooltip' => 'زۆرترین بەرزیی رێگەپێدراو بۆ بارکردنی وێنە بە پیکسڵ (پیکس).',
'image_max_size_tooltip' => 'زۆرترین قەبارەی رێگەپێدراوی فایلی بارکردنی وێنە بە کیلۆبایت (کب).',
'image_max_width_tooltip' => 'زۆرترین پانی ڕێگەپێدراوی بارکردنی وێنە بە پێکسڵ (پیکس).',
'image_restrictions' => 'سنووربەندییەکانی بارکردنی وێنە',
'include_hsn' => 'پاڵپشتی بۆ کۆدەکانی (ئێیچ ئێس ئێن) لەخۆ بگرە',
'info' => 'زانیاری',
'info_configuration' => 'زانیاری فڕۆشتگا',
'input_groups' => 'گروپەکانی زانیارییە پێدراوەکان',
'integrations' => 'یەکگرتنەکان',
'integrations_configuration' => 'یەکگرتنەکانی لایەنی سێیەم',
'invoice' => 'فاکتۆرە',
'invoice_configuration' => 'ڕێکخستنەکانی چاپی فاکتورە',
'invoice_default_comments' => 'سەرنجەکانی فاکتۆرەی بنەڕەتیی',
'invoice_email_message' => 'تێمپڵەیتی ئیمەیڵی فاکتۆرە',
'invoice_enable' => 'بەفاکتۆرەکردن چالاک بکە',
'invoice_printer' => 'پرنتەری فاکتۆرە',
'invoice_type' => 'جۆری فاکتۆرە',
'is_readable' => 'دەتواندرێت بخوێندرێتەوە، بەڵام ڕێگەپێدانەکان بەهەڵە داندراون. تکایە لەسەر ٦٤٠ یان ٦٦٠ دایبنێ و ڕفرێشی بکەوە.',
'is_writable' => 'دەتوانرێت بنووسرێتەوە، بەڵام ڕێگەپێدانەکان بەهەڵە دانراون. تکایە لەسەر ٧٥٠ دایبنێ و ڕفرێشی بکەوە.',
'item_markup' => '',
'jsprintsetup_required' => 'ئاگاداری: ئەم کاراییە تەنها لەو کاتەدا کاردەکات کە زیادکراوی FireFox jsPrintSetupت دامەزرابێت. سەرەڕای ئەمە هێشتا دەتەوێت پاشەکەوتی بکە؟',
'language' => 'زمان',
'last_used_invoice_number' => 'کۆتا ژمارەی فاکتۆرەی بەکارهاتوو',
'last_used_quote_number' => 'کۆتا ژمارەی دەرخستەی نرخەکانی بەکارهاتوو',
'last_used_work_order_number' => 'کۆتا ژمارەی بەکارهاتووی داواکاری کار',
'left' => 'چەپ',
'license' => 'مۆڵەت',
'license_configuration' => 'بەیاننامەی مۆڵەت',
'line_sequence' => 'زنجیرەی هێڵ',
'lines_per_page' => 'هێڵەکانی هەر پەڕەیەک',
'lines_per_page_number' => 'هێڵەکانی هەر پەڕەیەک دەبێت ژمارە بێت.',
'lines_per_page_required' => 'خانەی هێڵەکانی هەر پەڕەیەک پێویستە.',
'locale' => 'خۆماڵیکردن',
'locale_configuration' => 'ڕێکخستنی خۆماڵیکردن',
'locale_info' => 'زانیاریی ڕێکخستنی خۆماڵیکردن',
'location' => 'کۆگا',
'location_configuration' => 'شوێنی کۆگا',
'location_info' => 'زانیاری ڕێکخستنی شوێن',
'login_form' => 'ستایلی فۆڕمی چوونەژوورەوە',
'logout' => 'دەتەوێت پاڵپشت دروست بکەیت پێش چوونە دەرەوە؟ کرتە بکە لەسەر [باشە] بۆ پاڵپشت دروستکردن یان [هەڵوەشاندنەوە] بۆ چوونە دەرەوە.',
'mailchimp' => 'مەیڵچیمپ',
'mailchimp_api_key' => 'کلیلی (ئەی پی ئای)ی مەیڵچیمپ',
'mailchimp_configuration' => 'ڕێکخستنی مەیڵچیمپ',
'mailchimp_key_successfully' => 'کلیلی (ئەی پی ئای) دروستە.',
'mailchimp_key_unsuccessfully' => 'کلیلی (ئەی پی ئای) نادروستە.',
'mailchimp_lists' => 'لیست(ەکان)ی مەیڵچیمپ',
'mailchimp_tooltip' => 'کرتە لەسەر ئایکۆنی کلیلی (ئەی پی ئای) بکە.',
'message' => 'نامە',
'message_configuration' => 'ڕێکخستنی نامە',
'msg_msg' => 'دەقی نامەی پاشەکەوتکراو',
'msg_msg_placeholder' => 'ئەگەر دەتەوێت تێمپڵەیتی کورتەنامە بەکاربهێنیت ئەوا نامەکەت لێرەدا پاشەکەوت بکە، ئەگەرنا خانەکە بە بەتاڵی بهێڵەرەوە.',
'msg_pwd' => 'وشەی نهێنی کورتەنامە-ئەی پی ئای',
'msg_src' => 'ناسنامەی نێردەری کورتەنامە-ئەی پی ئای',
'msg_src_required' => 'خانەی ناسنامەی کورتەنامە-ئەی پی ئای پێویستە',
'msg_uid' => 'ناوی بەکارهێنەری کورتەنامە-ئەی پی ئای',
'msg_uid_required' => 'خانەی ناوی بەکارهێنەری کورتەنامە-ئەی پی ئای پێویستە',
'multi_pack_enabled' => 'چەندین پاکێج بۆ هەر ئایتمێک',
'no_risk' => 'هیچ مەترسیەکی ئاسایش یا لاوازبوون نییە.',
'none' => 'هیچ',
'notify_alignment' => 'شوێنی دەرکەوتنی ئاگادارکردنەوە',
'number_format' => 'فۆڕماتی ژمارە',
'number_locale' => 'خۆماڵیکردن',
'number_locale_invalid' => 'ناوچەی داخڵکراو نادروستە. بۆ دۆزینەوەی ناوچەیەکی دروست، بەستەرەکەی ناو ئامرازەکە بپشکنە.',
'number_locale_required' => 'خانەی ژمارەی ناوچە پێویستە.',
'number_locale_tooltip' => 'لە ڕێگەی ئەم بەستەرەوە ناوچەی گونجاو بدۆزەرەوە.',
'os_timezone' => 'ناوچەی کاتی OSPOS:',
'ospos_info' => 'زانیاری دامەزراندنی OSPOS',
'payment_options_order' => 'ڕیزبەندی بژاردەکانی پارەدان',
'payment_reference_code_length_limits' => 'کۆدی مەرجعی پارەدان<br>سنووری درێژی',
'payment_reference_code_length_max_label' => 'زۆرترین',
'payment_reference_code_length_min_label' => 'کەمترین',
'perm_risk' => 'ڕێگەپێدانی هەڵە ئەم نەرمەکاڵایە دەخاتە مەترسییەوە.',
'phone' => 'تەلەفوونی کۆمپانیا',
'phone_required' => 'خانەی تەلەفوونی کۆمپانیا پێویستە.',
'print_bottom_margin' => 'پەراوێزی خوارەوە',
'print_bottom_margin_number' => 'پەراوێزی خوارەوە دەبێت ژمارە بێت.',
'print_bottom_margin_required' => 'خانەی پەراوێزی خوارەوە پێویستە.',
'print_delay_autoreturn' => 'گەڕانەوەی خۆکارانە بۆ دواکەوتنی فرۆشتن',
'print_delay_autoreturn_number' => 'خانەی گەڕانەوەی خۆکارانە بۆ دواکەوتنی فرۆشتن پێویستە.',
'print_delay_autoreturn_required' => 'گەڕانەوەی خۆکارانە بۆ دواکەوتنی فرۆشتن دەبێت ژمارە بێت.',
'print_footer' => 'چاپی فووتەری وێبگەڕ',
'print_header' => 'چاپی هێدەری وێبگەڕ',
'print_left_margin' => 'پەراوێزی چەپ',
'print_left_margin_number' => 'پەراوێزی چەپ دەبێت ژمارە بێت.',
'print_left_margin_required' => 'خانەی پەراوێزی چەپ پێویستە.',
'print_receipt_check_behaviour' => 'چاپی خانەی هەڵبژاردنی فاکتورە',
'print_receipt_check_behaviour_always' => 'هەمیشە هەڵبژێردراوە',
'print_receipt_check_behaviour_last' => 'کۆتا هەڵبژاردنت بیر بێت',
'print_receipt_check_behaviour_never' => 'هەرگیز هەڵنەبژێردراوە',
'print_right_margin' => 'پەراوێزی ڕاست',
'print_right_margin_number' => 'پەراوێزی ڕاست ئەبێت ژمارە بێت.',
'print_right_margin_required' => 'خانەی پەراوێزی ڕاست پێویستە.',
'print_silently' => 'دیالۆگی چاپ نیشان بدە',
'print_top_margin' => 'پەراوێزی سەرەوە',
'print_top_margin_number' => 'پەراوێزی سەرەوە دەبێت ژمارە بێت.',
'print_top_margin_required' => 'خانەی پەراوێزی سەرەوە پێویستە.',
'quantity_decimals' => 'ژمارەی خانەی دەیان',
'quick_cash_enable' => '',
'quote_default_comments' => 'سەرنجە بنەڕەتییەکانی دەرخستەی نرخەکان',
'receipt' => 'پسوڵە',
'receipt_category' => '',
'receipt_configuration' => 'ڕێکخستنەکانی چاپی پسوڵە',
'receipt_default' => 'بنەڕەتیی',
'receipt_font_size' => 'قەبارەی فۆنت',
'receipt_font_size_number' => 'قەبارەی فۆنت دەبێت ژمارە بێت.',
'receipt_font_size_required' => 'خانەی قەبارەی فۆنت پێویستە.',
'receipt_info' => 'زانیاری ڕێکخستنی پسوڵە',
'receipt_printer' => 'چاپکەری بلیت',
'receipt_short' => 'کورت',
'receipt_show_company_name' => 'ناوی کۆمپانیا نیشان بدە',
'receipt_show_description' => 'دەربارە نیشان بدە',
'receipt_show_serialnumber' => 'ژمارەی زنجیرەیی نیشان بدە',
'receipt_show_tax_ind' => 'دەرخەری باج نیشان بدە',
'receipt_show_taxes' => 'باجەکان نیشان بدە',
'receipt_show_total_discount' => 'داشکاندنی گشتی نیشان بدە',
'receipt_template' => 'تێمپڵەیتی پسوڵە',
'receiving_calculate_average_price' => 'هەژمارکردنی نرخی تێکڕا (وەرگیراوەکان)',
'recv_invoice_format' => 'فۆڕماتی فاکتورەی وەرگیراوەکان',
'register_mode_default' => 'دۆخی تۆمارکردنی بنەڕەتیی',
'report_an_issue' => 'ڕاپۆرتکردنی کێشەیەک',
'return_policy_required' => 'خانەی ڕێکاری گەڕانەوە پێویستە.',
'reward' => 'پاداشت',
'reward_configuration' => 'ڕێکخستنی پاداشت',
'right' => 'ڕاست',
'sales_invoice_format' => 'فۆڕماتی فاکتورەی فرۆشتن',
'sales_quote_format' => 'فۆڕماتی دەرخستەی نرخەکانی فرۆشتن',
'mailpath_invalid' => 'ڕێچکەی sendmail نادروستە. تەنها پیت، ژمارە، هێڵی بەستەرەوە، هێڵی ژێرەوە، سلاشی ڕاست، سلاشی چەپ، دوو خاڵ، بۆشایی و خاڵ ڕێگەپێدراون.',
'saved_successfully' => 'پاشەکەوتکردنی ڕێکخستن سەرکەوتوو بوو.',
'saved_unsuccessfully' => 'پاشەکەوتکردنی ڕێکخستن سەرکەوتوو نەبوو.',
'security_issue' => 'ئاگادارکردنەوەی لاوازی ئاسایش',
'server_notice' => 'تکایە ئەم زانیاریانەی خوارەوە بەکاربهێنە بۆ ڕاپۆرتکردنی کێشە.',
'service_charge' => '',
'show_due_enable' => '',
'show_office_group' => 'ئایکۆنی ئۆفیس پیشان بدە',
'statistics' => 'ناردنی ئامار',
'statistics_tooltip' => 'ناردنی ئامارەکان بە مەبەستی پەرەپێدان و باشترکردنی تایبەتمەندییەکان.',
'stock_location' => 'شوێنی کۆگا',
'stock_location_duplicate' => 'شوێنی کۆگا دەبێت بێهاوتا بێت.',
'stock_location_invalid_chars' => "شوێنی کۆگا ناتوانێت '_' لەخۆبگرێت.",
'stock_location_required' => 'خانەی شوێنی کۆگا پێویستە.',
'suggestions_fifth_column' => '',
'suggestions_first_column' => 'ستوونی ١',
'suggestions_fourth_column' => '',
'suggestions_layout' => 'نەخشەی پێشنیارەکانی گەڕان',
'suggestions_second_column' => 'ستوونی ٢',
'suggestions_third_column' => 'ستوونی ٣',
'system_conf' => 'دامەزراندن و ڕێکخستن',
'system_info' => 'زانیاری سیستەم',
'table' => 'مێز',
'table_configuration' => 'ڕێکخستنی جەدۆل',
'takings_printer' => 'چاپکەری پسوڵە',
'tax' => 'باج',
'tax_category' => 'پۆلێنی باج',
'tax_category_duplicate' => 'پۆلێنی باجی داخڵکراو پێشتر بوونی هەیە.',
'tax_category_invalid_chars' => 'پلێنی باجی داخڵکراو نادروستە.',
'tax_category_required' => 'پۆلێنی باج پێویستە.',
'tax_category_used' => 'پۆلێنی باج ناتوانرێت بسڕدرێتەوە چونکە بەکاردەهێنرێت.',
'tax_configuration' => 'ڕێکخستنی باج',
'tax_decimals' => 'خانەی دەیانی باج',
'tax_id' => 'ناسنامەی باج',
'tax_included' => 'باج لەخۆدەگرێت',
'theme' => 'ڕووکار',
'theme_preview' => 'پێشبینینی ڕووکار:',
'thousands_separator' => 'جیاکەرەوەی هەزاران',
'timezone' => 'ناوچەی کات',
'timezone_error' => 'ناوچەی کاتی OSPOS جیاوازە لە ناوچەی کاتی ناوخۆیی خۆت.',
'top' => 'سەرەوە',
'use_destination_based_tax' => 'بەکارهێنانی باجی بنەمادار بە شوێنی مەبەست',
'user_timezone' => 'ناوچەی کاتی ناوخۆیی:',
'website' => 'ماڵپەڕ',
'wholesale_markup' => '',
'work_order_enable' => 'پاڵپشتی داواکاری کار',
'work_order_format' => 'فۆڕماتی داواکاری کار',
];