diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 27c631fbb..1e791af94 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -204,7 +204,7 @@ FloCafe runs on real business data that must survive software upgrades. ## Translations and i18n -FloCafe currently provides translations for English (`en`), Spanish (`es`), French (`fr`), Brazilian Portuguese (`pt`), Russian (`ru`), Filipino (`fil`), Turkish (`tr`), Persian (`fa`, including RTL support), Arabic (`ar`, including RTL support), Urdu (`ur`, including RTL support), German (`de`), Italian (`it`), Japanese (`ja`), Simplified Chinese (`zh`), Traditional Chinese for Taiwan (`zh-tw`), Korean (`ko`), Bahasa Indonesia (`id`), Dutch (`nl`), Hindi (`hi`), Bengali/Bangla (`bn`), Albanian (`sq`), Vietnamese (`vi`), Thai (`th`), Nepali (`ne`), Hausa (`ha`), Javanese (`jv`), Marathi (`mr`), Swahili (`sw`), and Punjabi (`pa`). +FloCafe currently provides translations for English (`en`), Spanish (`es`), French (`fr`), Brazilian Portuguese (`pt`), Russian (`ru`), Filipino (`fil`), Turkish (`tr`), Persian (`fa`, including RTL support), Arabic (`ar`, including RTL support), Urdu (`ur`, including RTL support), German (`de`), Italian (`it`), Japanese (`ja`), Simplified Chinese (`zh`), Traditional Chinese for Taiwan (`zh-tw`), Korean (`ko`), Bahasa Indonesia (`id`), Dutch (`nl`), Hindi (`hi`), Bengali/Bangla (`bn`), Albanian (`sq`), Vietnamese (`vi`), Thai (`th`), Nepali (`ne`), Hausa (`ha`), Javanese (`jv`), Marathi (`mr`), Swahili (`sw`), Punjabi (`pa`), and Telugu (`te`). - **Existing languages:** Narrowly scoped fixes and improvements to existing translation strings are always welcome. Verify changes with `npm run i18n:check`. - **New languages:** Adding an entirely new language requires maintainer coordination through an issue first. diff --git a/README.md b/README.md index ee9b51356..354f047c5 100644 --- a/README.md +++ b/README.md @@ -194,7 +194,7 @@ Both scripts ask whether to keep application data. Do not choose their data-purg - **Offline-first architecture:** Local SQLite storage with auto-migrating schema and fail-closed safety. - **Granular roles & permissions:** Owner, Manager, Cashier, Server, and Chef roles with context-aware access policies. -- **Multi-language support:** 29 localized languages with full bidirectional RTL rendering (Arabic, Persian, Urdu). +- **Multi-language support:** 30 localized languages with full bidirectional RTL rendering (Arabic, Persian, Urdu). - **131 Country profiles:** 109 world currencies with localized phone parsing, number formatting, and timezone handling. - **Country tax packs:** Signed regional tax pack integration and manual rule engine. - **Automated database backups:** Pre-migration automatic snapshots, manual exports, and optional Google Drive sync. @@ -248,6 +248,7 @@ FloCafe includes UI translations for: - Marathi - Swahili - Punjabi +- Telugu UI language is independent of store country and regional settings, and tax calculation rules remain a separate concern. For details on contributing translations or adding languages, see the [Internationalization and translation guide](docs/architecture/internationalization.md). diff --git a/docs/architecture/frontend.md b/docs/architecture/frontend.md index b8793be72..ee08c4eb1 100644 --- a/docs/architecture/frontend.md +++ b/docs/architecture/frontend.md @@ -542,10 +542,10 @@ and the auth store keeps the languages that failed. Every print action calls a receipt warning saying English labels were used. A receipt that renders in the wrong language is a financial document, not a cosmetic bug. -## Internationalization: 29 locales +## Internationalization: 30 locales [`frontend/src/lib/i18n/languages.ts`](../../frontend/src/lib/i18n/languages.ts) is the renderer's -registry. It holds 29 entries, and +registry. It holds 30 entries, and [`frontend/src/lib/i18n/messages/`](../../frontend/src/lib/i18n/messages) holds one JSON file per entry. Each registry entry carries the BCP-47 locale tag, the native name, the text direction, the `selectable` flag, and a dynamic chunk loader. @@ -667,7 +667,7 @@ frontend/src/ │ └── updates/ Update download prompt and install guard dialog ├── hooks/ Printer, KDS, theme, update, cash, approver, and formatting hooks ├── lib/ -│ ├── i18n/ Language registry, loader, and the 29 message files +│ ├── i18n/ Language registry, loader, and the 30 message files │ ├── printer/ Encoders, document builders, warnings, WebUSB bridge, │ │ and the delivery-slip encoder and browser renderer │ ├── updates/ Beta channel, auto-check, and restart-and-install helpers diff --git a/docs/architecture/internationalization.md b/docs/architecture/internationalization.md index f7c2529c0..e8d7b02c8 100644 --- a/docs/architecture/internationalization.md +++ b/docs/architecture/internationalization.md @@ -1,6 +1,6 @@ # Internationalization -FloCafe supports 29 UI languages. This page describes how a language is declared, loaded, and +FloCafe supports 30 UI languages. This page describes how a language is declared, loaded, and validated, and how the UI language stays separate from a store's regional settings. ## Source of truth and the parity rule @@ -15,8 +15,8 @@ translation test fails. `npm run i18n:check` runs `tests/translations.test.ts`, registry and file consistency, key parity, ICU validity, placeholder and tag parity, per-language completeness, and frontend key safety. -The 29 committed catalogues are: `ar`, `bn`, `de`, `en`, `es`, `fa`, `fil`, `fr`, `ha`, `hi`, `id`, -`it`, `ja`, `jv`, `ko`, `mr`, `ne`, `nl`, `pa`, `pt`, `ru`, `sq`, `sw`, `th`, `tr`, `ur`, `vi`, `zh`, `zh-tw`. +The 30 committed catalogues are: `ar`, `bn`, `de`, `en`, `es`, `fa`, `fil`, `fr`, `ha`, `hi`, `id`, +`it`, `ja`, `jv`, `ko`, `mr`, `ne`, `nl`, `pa`, `pt`, `ru`, `sq`, `sw`, `te`, `th`, `tr`, `ur`, `vi`, `zh`, `zh-tw`. ## The registry diff --git a/docs/architecture/printing.md b/docs/architecture/printing.md index 61d23aefe..7b5b55722 100644 --- a/docs/architecture/printing.md +++ b/docs/architecture/printing.md @@ -309,7 +309,7 @@ The drawer pulse is the ESC/POS sequence `ESC p 0 0x19 0xFA`. It is emitted only `shared/print/width.ts` measures in grapheme clusters and display cells, not UTF-16 code units. A combining mark attaches to its base, an Indic conjunct is never split at a virama -(U+094D, U+09CD, U+0A4D), and a ZWNJ stays with the grapheme it follows. Measuring in code units silently +(U+094D, U+09CD, U+0A4D, U+0C4D), and a ZWNJ stays with the grapheme it follows. Measuring in code units silently breaks every non-BMP and every combining-script receipt, which is why every renderer in the pipeline uses this helper rather than `String.length`. diff --git a/docs/guides/adding-a-language.md b/docs/guides/adding-a-language.md index 9137d917a..5c919ff29 100644 --- a/docs/guides/adding-a-language.md +++ b/docs/guides/adding-a-language.md @@ -64,8 +64,8 @@ While translating: such as an email or IP address. Anything else renders as untranslated English to your users, and the check will reject it. - For a language with combining marks, the value must be in Unicode NFC. `tests/translations.test.ts` - enforces NFC for the languages it checks by name, which are `ha`, `jv`, `mr`, `ne`, `pa`, `ru`, `sw`, `th`, and `vi`. -- Avoid invisible formatting characters. The Russian, Javanese, and Marathi validators in + enforces NFC for the languages it checks by name, which are `ha`, `jv`, `mr`, `ne`, `pa`, `ru`, `sw`, `te`, `th`, and `vi`. +- Avoid invisible formatting characters. The Russian, Javanese, Marathi, and Telugu validators in `tests/translations.test.ts` reject U+200B, U+200C, U+200D, U+00AD, and U+FEFF, because they corrupt printed text silently. Other language validators do not check for them yet, so this is your responsibility to get right rather than something the test will catch. @@ -74,7 +74,7 @@ While translating: ## 4. Register the intentional-identical keys Each language has a `_INTENTIONAL_IDENTICAL` set in `tests/translations.test.ts` listing the -keys allowed to be English-identical, most with a comment saying why. There are 24 such sets. +keys allowed to be English-identical, most with a comment saying why. There are 25 such sets. Add an entry for every key you deliberately left identical, with a comment giving the reason. Without the entry the check fails, and the failure is what keeps an accidentally untranslated string from @@ -129,13 +129,13 @@ language is not covered by them until you add it: | File | Array | Current coverage | | --- | --- | --- | -| `tests/phase3-print-regressions.test.ts` | `languages` | 28 of 29; omits `ar`. | -| `tests/issue-241-localized-errors.test.ts` | `LANGUAGES` | All 29 (`Object.keys(LANGUAGE_REGISTRY)`). | -| `tests/rtl-setup-auth-settings.test.ts` | `languages` | 25 of 29; omits `ar`, `de`, `fil`, `tr`. | -| `tests/browser-receipts.test.ts` | loop array | 25 of 29; omits `ar`, `de`, `fil`, `tr`. | -| `tests/i18n-audit-remediations.test.ts` | two loop arrays | 25 of 29 each; omits `ar`, `de`, `fil`, `tr`. | -| `tests/rtl-kds-server-whatsapp.test.ts` | four loop arrays | 25 of 29 for the all-language loops, 23 for the LTR-only loop. | -| `tests/rtl-dashboard-pos-common.test.ts` | two LTR-only loop arrays | 23 of 29; omits the RTL languages plus `de`, `fil`, `tr`. | +| `tests/phase3-print-regressions.test.ts` | `languages` | 29 of 30; omits `ar`. | +| `tests/issue-241-localized-errors.test.ts` | `LANGUAGES` | All 30 (`Object.keys(LANGUAGE_REGISTRY)`). | +| `tests/rtl-setup-auth-settings.test.ts` | `languages` | 26 of 30; omits `ar`, `de`, `fil`, `tr`. | +| `tests/browser-receipts.test.ts` | loop array | 26 of 30; omits `ar`, `de`, `fil`, `tr`. | +| `tests/i18n-audit-remediations.test.ts` | two loop arrays | 26 of 30 each; omits `ar`, `de`, `fil`, `tr`. | +| `tests/rtl-kds-server-whatsapp.test.ts` | four loop arrays | 26 of 30 for the all-language loops, 24 for the LTR-only loop. | +| `tests/rtl-dashboard-pos-common.test.ts` | two LTR-only loop arrays | 24 of 30; omits the RTL languages plus `de`, `fil`, `tr`. | This is a known baseline, not something this procedure introduces. Several of these arrays already omit registered locales, so they are not a reliable coverage signal. The arrays whose names include diff --git a/docs/reference/translation-terminology.md b/docs/reference/translation-terminology.md index d456fd6e3..66213a35d 100644 --- a/docs/reference/translation-terminology.md +++ b/docs/reference/translation-terminology.md @@ -27,8 +27,8 @@ Pinned by `tests/print-kernel.test.ts`. ## Indic conjuncts are never split -A Devanagari, Bengali, or Gurmukhi conjunct is a single grapheme cluster and must stay one. The -virama characters that join them, U+094D in Devanagari, U+09CD in Bengali, and U+0A4D in Gurmukhi, +A Devanagari, Bengali, Gurmukhi, or Telugu conjunct is a single grapheme cluster and must stay one. The +virama characters that join them, U+094D in Devanagari, U+09CD in Bengali, U+0A4D in Gurmukhi, and U+0C4D in Telugu, are the ones a naive splitter would break. Pinned by `tests/print-kernel.test.ts`, which asserts that wrapping a two-cluster Indic string at one @@ -55,7 +55,7 @@ is invisible on screen and corrupts comparison, searching, and print labels. identically and wrap identically after normalisation, which is what makes NFC a requirement rather than a preference. `tests/translations.test.ts` rejects a `vi.json` value that is not already NFC. -The same NFC requirement is enforced for `ha.json`, `jv.json`, `mr.json`, `ne.json`, `pa.json`, `ru.json`, `sw.json`, and `th.json`. +The same NFC requirement is enforced for `ha.json`, `jv.json`, `mr.json`, `ne.json`, `pa.json`, `ru.json`, `sw.json`, `te.json`, and `th.json`. ## Albanian and Vietnamese on a generic thermal printer @@ -198,6 +198,12 @@ pay-out on both the dashboard and the Z-report, and takeaway is `ਟੇਕਅਵ `pos.*`. Gurmukhi virama conjuncts (`ਪ੍ਰ`, `ਸ੍ਰ`) and combining signs (`ੰ` tippi, `ਂ` bindi, `ੱ` addak, `਼` nukta) must remain NFC-normalized and attached to their base consonant. +**Telugu.** Subtotal `ఉప మొత్తం` and grand total `మొత్తం` are distinct labels and must stay +distinct on the receipt. The vegetarian tags are `శాకాహారం` and the non-vegetarian tags +`మాంసాహారం`, identical between `pos.*` and `products.*`. Cash movement uses `నగదు జమ` for pay-in +and `నగదు ఉపసంహరణ` for pay-out, identically on the dashboard and on the Z-report. Takeaway is +`టేక్అవే` and delivery is `డెలివరీ`. + ## Verification The contracts on this page are pinned by `tests/print-kernel.test.ts`, diff --git a/frontend/e2e/phase7-setup-print-i18n.spec.ts b/frontend/e2e/phase7-setup-print-i18n.spec.ts index bd9cc6556..1f0681871 100644 --- a/frontend/e2e/phase7-setup-print-i18n.spec.ts +++ b/frontend/e2e/phase7-setup-print-i18n.spec.ts @@ -103,6 +103,7 @@ const LABELS: Record = web: 'ਵੈੱਬ ਪ੍ਰਿੰਟ (ਬ੍ਰਾਊਜ਼ਰ)', whatsapp: 'WhatsApp ਸ਼ੇਅਰ', }, + te: { basic: 'ప్రాథమిక రసీదు (థర్మల్)', web: 'వెబ్ ప్రింట్ (బ్రౌజర్)', whatsapp: 'WhatsApp షేర్' }, }; async function loginAsOwner(page: Page): Promise { diff --git a/frontend/e2e/telugu-live-evidence.spec.ts b/frontend/e2e/telugu-live-evidence.spec.ts new file mode 100644 index 000000000..ef6808fe3 --- /dev/null +++ b/frontend/e2e/telugu-live-evidence.spec.ts @@ -0,0 +1,575 @@ +import { test, expect } from '@playwright/test'; +import * as fs from 'fs'; +import * as os from 'os'; +import * as path from 'path'; +import { E2E_BASE_URL, E2E_KDS_BASE_URL, E2E_SERVER_APP_BASE_URL } from './helpers/urls'; +import { E2E_PASSWORD, getE2eToken, setLanguage } from './helpers/test-auth'; + +// eslint-disable-next-line @typescript-eslint/no-require-imports +const { formatDailySalesWhatsAppMessage } = require('../../dist/main/services/daily-sales-export'); + +const LOCAL_EVIDENCE_BASE = path.join(os.homedir(), '.no-mistakes', 'evidence'); +const EVIDENCE_DIR = + process.env.EVIDENCE_DIR || + (fs.existsSync(LOCAL_EVIDENCE_BASE) + ? path.join(LOCAL_EVIDENCE_BASE, '01M6TWNVZRE2MT9WHN20Z3GYKA') + : path.join(os.tmpdir(), 'flocafe-telugu-e2e-evidence')); + +function ensureEvidenceDir() { + if (!fs.existsSync(EVIDENCE_DIR)) { + fs.mkdirSync(EVIDENCE_DIR, { recursive: true }); + } +} + +test.describe('Live Telugu (te / te-IN) E2E verification across FloCafe surfaces', () => { + test('1. Setup wizard offers Telugu (తెలుగు / TE), switches html lang="te-IN" dir="ltr", and renders localized steps', async ({ + page, + }) => { + ensureEvidenceDir(); + await page.route('**/api/auth/setup/status', (route) => { + route.fulfill({ + status: 200, + contentType: 'application/json', + body: JSON.stringify({ needsSetup: true, masterPinAvailable: true }), + }); + }); + + await page.goto(`${E2E_BASE_URL}/setup`); + const teluguBtn = page.locator('button', { hasText: 'తెలుగు' }).first(); + await expect(teluguBtn).toBeVisible(); + await expect(teluguBtn).toContainText('TE'); + await teluguBtn.click(); + + await expect(page.locator('html')).toHaveAttribute('lang', 'te-IN'); + await expect(page.locator('html')).toHaveAttribute('dir', 'ltr'); + await expect(page.getByText('FloCafe కు స్వాగతం')).toBeVisible(); + + await page.locator('.max-h-72 button').first().click(); + await page.screenshot({ + path: path.join(EVIDENCE_DIR, '01-setup-wizard-telugu.png'), + fullPage: true, + }); + }); + + test('2. Main POS, Settings, Print-Test, Server App, KDS Standalone, Customer Display, Web Print Receipts, and WhatsApp Reports in Telugu', async ({ + page, + browser, + request, + }) => { + ensureEvidenceDir(); + const ownerToken = getE2eToken('e2e-owner', 'owner@flo.local', 'owner'); + const managerToken = getE2eToken('e2e-manager', 'manager@flo.local', 'manager'); + const serverToken = getE2eToken('e2e-server', 'server@flo.local', 'server'); + const headers = { Authorization: `Bearer ${ownerToken}` }; + + const createdCategoryIds: string[] = []; + const createdProductIds: string[] = []; + const createdOrderIds: number[] = []; + let customerDisplayTokenId: string | number | null = null; + + const initialBizSettingsRes = await request.get(`${E2E_BASE_URL}/api/settings/business`, { + headers, + }); + expect(initialBizSettingsRes.ok()).toBeTruthy(); + const initialBizSettings = (await initialBizSettingsRes.json()) as { language?: string }; + const initialLanguage = + typeof initialBizSettings.language === 'string' && initialBizSettings.language + ? initialBizSettings.language + : 'en'; + + try { + // Seed Telugu sample catalog items on the live API to verify POS, Server App, and KDS rendering + const catMainRes = await request.post(`${E2E_BASE_URL}/api/categories`, { + headers, + data: { name: 'ప్రధాన వంటకాలు', color: '#4ECDC4', icon: '🍛', sort_order: 10 }, + }); + expect(catMainRes.ok()).toBeTruthy(); + const catMain = (await catMainRes.json()).category; + createdCategoryIds.push(catMain.id); + + const catStartersRes = await request.post(`${E2E_BASE_URL}/api/categories`, { + headers, + data: { name: 'స్టార్టర్లు', color: '#FF6B6B', icon: '🍟', sort_order: 11 }, + }); + expect(catStartersRes.ok()).toBeTruthy(); + const catStarters = (await catStartersRes.json()).category; + createdCategoryIds.push(catStarters.id); + + const prodBiryaniRes = await request.post(`${E2E_BASE_URL}/api/products`, { + headers, + data: { + category_id: catMain.id, + name: 'హైదరాబాదీ బిర్యానీ', + price: 320, + tax_category_id: 'standard', + tax_behavior: 'exclusive', + track_inventory: false, + is_active: true, + }, + }); + expect(prodBiryaniRes.ok()).toBeTruthy(); + const prodBiryani = (await prodBiryaniRes.json()).product; + createdProductIds.push(prodBiryani.id); + + const prodPunuguluRes = await request.post(`${E2E_BASE_URL}/api/products`, { + headers, + data: { + category_id: catStarters.id, + name: 'పునుగులు', + price: 250, + tax_category_id: 'standard', + tax_behavior: 'exclusive', + track_inventory: false, + is_active: true, + }, + }); + expect(prodPunuguluRes.ok()).toBeTruthy(); + const prodPunugulu = (await prodPunuguluRes.json()).product; + createdProductIds.push(prodPunugulu.id); + + // Log into Main POS as owner and switch language to Telugu ('te') + await page.goto(`${E2E_BASE_URL}/auth/login`); + await page.locator('#email').fill('owner@flo.local'); + await page.locator('#password').fill(E2E_PASSWORD); + await page.locator('button[type="submit"]').click(); + await page.waitForURL('**/pos/**', { timeout: 20000 }); + + await setLanguage(page, 'te'); + await page.goto(`${E2E_BASE_URL}/pos`); + await expect(page.locator('html')).toHaveAttribute('lang', 'te-IN'); + await expect(page.locator('html')).toHaveAttribute('dir', 'ltr'); + + const fontFamily = await page.evaluate(() => getComputedStyle(document.body).fontFamily); + expect(fontFamily).toContain('Noto Sans Telugu'); + + await expect(page.getByText('హైదరాబాదీ బిర్యానీ').first()).toBeVisible(); + await expect(page.getByText('పునుగులు').first()).toBeVisible(); + await page.getByText('హైదరాబాదీ బిర్యానీ').first().click(); + await page.getByText('పునుగులు').first().click(); + + await page.screenshot({ + path: path.join(EVIDENCE_DIR, '02-pos-telugu-seed-catalog.png'), + fullPage: true, + }); + + // Verify Settings and /print-test in Telugu, plus live Web Print HTML & KOT & WhatsApp receipt + await page.evaluate(() => { + const raw = localStorage.getItem('pos-settings'); + const parsed = raw ? JSON.parse(raw) : { state: {}, version: 3 }; + parsed.state = { + ...parsed.state, + language: 'te', + kotPrintingEnabled: true, + }; + localStorage.setItem('pos-settings', JSON.stringify(parsed)); + }); + await page.goto(`${E2E_BASE_URL}/print-test`); + const basicBtn = page.getByRole('button', { name: 'ప్రాథమిక రసీదు (థర్మల్)', exact: true }); + const webPrintBtn = page.getByRole('button', { name: 'వెబ్ ప్రింట్ (బ్రౌజర్)', exact: true }); + const whatsappBtn = page.getByRole('button', { name: 'WhatsApp షేర్', exact: true }); + const kotBtn = page.getByRole('button', { name: 'KOT (కిచెన్ టికెట్)', exact: true }); + await expect(basicBtn).toBeVisible(); + await expect(webPrintBtn).toBeVisible(); + await expect(whatsappBtn).toBeVisible(); + await expect(kotBtn).toBeVisible(); + await page.screenshot({ + path: path.join(EVIDENCE_DIR, '03-settings-and-print-test-telugu.png'), + fullPage: true, + }); + + // Download live Web Print receipt HTML from /print-test in Telugu + await webPrintBtn.click(); + const downloadBtn = page.getByRole('button', { name: 'HTML డౌన్లోడ్ చేయి', exact: true }); + await expect(downloadBtn).toBeVisible(); + const [download] = await Promise.all([page.waitForEvent('download'), downloadBtn.click()]); + const receiptHtmlPath = path.join(EVIDENCE_DIR, '07-web-print-receipt-telugu.html'); + await download.saveAs(receiptHtmlPath); + const billHtml = fs.readFileSync(receiptHtmlPath, 'utf8'); + expect(billHtml).toContain('lang="te-IN"'); + expect(billHtml).toContain('మీ సందర్శనకు ధన్యవాదాలు!'); + + // Capture live KOT browser print HTML from /print-test in Telugu + await kotBtn.click(); + await page.getByRole('button', { name: 'బ్రౌజర్ ప్రింట్', exact: true }).click(); + await page.evaluate(() => { + const win = window as unknown as { __capturedKotHtml?: string }; + win.__capturedKotHtml = ''; + window.open = (() => { + const doc = document.implementation.createHTMLDocument('KOT Preview'); + return { + document: doc, + focus: () => {}, + print: () => { + win.__capturedKotHtml = doc.documentElement.outerHTML; + }, + close: () => {}, + } as unknown as Window; + }) as typeof window.open; + }); + await page.getByRole('button', { name: 'టెస్ట్ రన్ చేయి', exact: true }).click(); + await expect + .poll(async () => + page.evaluate( + () => (window as unknown as { __capturedKotHtml?: string }).__capturedKotHtml || '', + ), + ) + .toContain('వంటగది'); + const kotHtml: string = await page.evaluate( + () => (window as unknown as { __capturedKotHtml?: string }).__capturedKotHtml || '', + ); + + // Render Web Print Receipt and KOT side-by-side in Chromium + const printContext = await browser.newContext({ viewport: { width: 960, height: 900 } }); + const printPage = await printContext.newPage(); + await printPage.setContent(` + + + Telugu Print Preview + +
${billHtml}
+
${kotHtml}
+ + + `); + await expect(printPage.getByText('మీ సందర్శనకు ధన్యవాదాలు!')).toBeVisible(); + await expect(printPage.getByText('వంటగది').first()).toBeVisible(); + await printPage.screenshot({ + path: path.join(EVIDENCE_DIR, '07-web-print-receipt-and-kot-telugu.png'), + fullPage: true, + }); + await printContext.close(); + + // Verify Server App (:3003/server-standalone) in Telugu and send a tableside order + const fixtureTableName = 'TE-1'; + const tablesListRes = await request.get(`${E2E_BASE_URL}/api/tables`, { + headers: { Authorization: `Bearer ${managerToken}` }, + }); + expect(tablesListRes.ok()).toBeTruthy(); + const tablesListBody = (await tablesListRes.json()) as { + tables?: Array<{ id: string | number; number: string; is_active?: number | boolean }>; + }; + let table = (tablesListBody.tables || []).find( + (t) => t.number === fixtureTableName && t.is_active !== 0 && t.is_active !== false, + ); + if (!table) { + const tableRes = await request.post(`${E2E_BASE_URL}/api/tables`, { + headers: { Authorization: `Bearer ${managerToken}` }, + data: { number: fixtureTableName, capacity: 4 }, + }); + expect(tableRes.ok()).toBeTruthy(); + table = ((await tableRes.json()) as { table: { id: string | number; number: string } }) + .table; + } + const tableName = table.number; + + const serverContext = await browser.newContext(); + const serverPage = await serverContext.newPage(); + await serverPage.goto(`${E2E_SERVER_APP_BASE_URL}/server-standalone`); + await serverPage.evaluate( + ([tok]) => { + localStorage.setItem('flocafe:server-app-token', tok); + localStorage.setItem( + 'pos-settings', + JSON.stringify({ state: { language: 'te' }, version: 3 }), + ); + }, + [serverToken], + ); + await serverPage.reload(); + await expect(serverPage.locator('html')).toHaveAttribute('lang', 'te-IN'); + await serverPage.getByRole('button', { name: new RegExp(tableName) }).click(); + const grid = serverPage.getByTestId('pos-product-grid'); + await expect(grid.getByPlaceholder('మెనూ వెతుకు')).toBeVisible(); + await grid.getByText('హైదరాబాదీ బిర్యానీ').first().click(); + await grid.getByText('పునుగులు').first().click(); + await serverPage.screenshot({ + path: path.join(EVIDENCE_DIR, '05-server-app-telugu.png'), + fullPage: true, + }); + await serverPage.getByRole('button', { name: 'వంటగదికి పంపు' }).first().click(); + await expect(serverPage.getByText('ఆర్డర్ పంపబడింది').first()).toBeVisible(); + await serverContext.close(); + + // Track the created dine-in order + const ordersRes = await request.get(`${E2E_BASE_URL}/api/orders`, { + headers, + params: { table_id: table.id, type: 'dine_in', per_page: 5 }, + }); + const { orders } = await ordersRes.json(); + for (const o of orders ?? []) { + createdOrderIds.push(o.id); + } + + // Create one preparing and one ready takeaway order for KDS and Customer Display + const prepOrderRes = await request.post(`${E2E_BASE_URL}/api/orders`, { + headers, + data: { + type: 'takeaway', + items: [{ product_id: prodBiryani.id, quantity: 1 }], + }, + }); + expect(prepOrderRes.status()).toBe(201); + const prepOrder = (await prepOrderRes.json()).order; + createdOrderIds.push(prepOrder.id); + await request.patch(`${E2E_BASE_URL}/api/orders/${prepOrder.id}/status`, { + headers, + data: { status: 'preparing' }, + }); + + const readyOrderRes = await request.post(`${E2E_BASE_URL}/api/orders`, { + headers, + data: { + type: 'takeaway', + items: [{ product_id: prodPunugulu.id, quantity: 2 }], + }, + }); + expect(readyOrderRes.status()).toBe(201); + const readyOrder = (await readyOrderRes.json()).order; + createdOrderIds.push(readyOrder.id); + await request.patch(`${E2E_BASE_URL}/api/orders/${readyOrder.id}/status`, { + headers, + data: { status: 'ready' }, + }); + + // Verify Standalone KDS (:3002/kds-standalone) in Telugu + const kdsContext = await browser.newContext(); + const kdsPage = await kdsContext.newPage(); + await kdsPage.addInitScript(() => { + localStorage.setItem( + 'pos-settings', + JSON.stringify({ state: { language: 'te' }, version: 3 }), + ); + }); + await kdsPage.goto(`${E2E_KDS_BASE_URL}/kds-standalone`); + await expect(kdsPage.getByTestId('kds-login-form')).toBeVisible(); + await kdsPage.getByTestId('kds-login-email').fill('manager@flo.local'); + await kdsPage.getByTestId('kds-login-password').fill(E2E_PASSWORD); + await kdsPage.getByTestId('kds-login-submit').click(); + await expect(kdsPage.getByTestId('kds-workspace')).toBeVisible(); + await expect(kdsPage.locator('html')).toHaveAttribute('lang', 'te-IN'); + await expect(kdsPage.getByText('హైదరాబాదీ బిర్యానీ').first()).toBeVisible(); + await kdsPage.screenshot({ + path: path.join(EVIDENCE_DIR, '04-kds-standalone-telugu.png'), + fullPage: true, + }); + await kdsContext.close(); + + // Verify Customer Display (/customer-display) in Telugu + const pairRes = await request.post(`${E2E_BASE_URL}/api/settings/customer-display/tokens`, { + headers, + data: { label: 'Telugu Lobby Display' }, + }); + expect(pairRes.ok()).toBeTruthy(); + const pairData = await pairRes.json(); + const rawToken = pairData.token?.raw_token || pairData.raw_token || pairData.token; + customerDisplayTokenId = pairData.token?.id || pairData.id || null; + + const cdContext = await browser.newContext(); + const cdPage = await cdContext.newPage(); + await cdPage.addInitScript(() => { + localStorage.setItem( + 'pos-settings', + JSON.stringify({ state: { language: 'te' }, version: 3 }), + ); + }); + if (typeof rawToken === 'string' && rawToken.startsWith('cdt_')) { + await cdPage.goto(`${E2E_BASE_URL}/customer-display/#token=${rawToken}`); + } else { + await cdPage.addInitScript((tok) => { + localStorage.setItem('token', tok); + }, ownerToken); + await cdPage.goto(`${E2E_BASE_URL}/customer-display/`); + } + await expect(cdPage.locator('html')).toHaveAttribute('lang', 'te-IN'); + await expect(cdPage.getByText('సిద్ధమవుతోంది').first()).toBeVisible({ timeout: 15000 }); + await expect(cdPage.getByText('పికప్ కోసం సిద్ధంగా ఉంది').first()).toBeVisible({ + timeout: 15000, + }); + await cdPage.screenshot({ + path: path.join(EVIDENCE_DIR, '06-customer-display-telugu.png'), + fullPage: true, + }); + await cdContext.close(); + + // Verify live Daily Sales & Daily Invoices exports and WhatsApp Daily Sales report in Telugu + const setLangRes = await request.put(`${E2E_BASE_URL}/api/settings/language`, { + headers, + data: { value: 'te' }, + }); + expect(setLangRes.ok()).toBeTruthy(); + + const waDailySalesBody: string = formatDailySalesWhatsAppMessage( + { + summary: { + business_date: '2026-11-07', + from_date: '2026-11-07', + to_date: '2026-11-07', + day_count: 1, + timezone: 'Asia/Kolkata', + business_day_start: '00:00', + currency: 'INR', + order_count: 2, + paid_bill_count: 2, + gross_collected: 598.5, + refunds_issued: 0, + net_collected: 598.5, + tax_total: 28.5, + discount_total: 0, + service_charge_total: 0, + packaging_charge_total: 0, + delivery_charge_total: 0, + known_cost_net_item_sales: 570, + ingredient_cost_total: 200, + gross_profit_total: 370, + gross_margin_percent: 64.91, + cost_coverage_status: 'known', + payment_methods: [ + { method: 'cash', total: 350 }, + { method: 'card', total: 248.5 }, + ], + tax_warning: '', + }, + days: [], + taxes: [], + items: [ + { + product_id: prodBiryani.id, + product_name: 'హైదరాబాదీ బిర్యానీ', + product_sku: 'TE-BIR-1', + quantity: 1, + gross_item_sales: 320, + item_discounts: 0, + net_item_sales: 320, + tax_amount: 16, + ingredient_cost: 120, + profit: 200, + margin_percent: 62.5, + cost_status: 'known', + }, + { + product_id: prodPunugulu.id, + product_name: 'పునుగులు', + product_sku: 'TE-PUN-1', + quantity: 1, + gross_item_sales: 250, + item_discounts: 0, + net_item_sales: 250, + tax_amount: 12.5, + ingredient_cost: 80, + profit: 170, + margin_percent: 68, + cost_status: 'known', + }, + ], + payment_lines: [], + }, + { + language: 'te', + locale: 'te-IN', + businessName: 'FloCafe హైదరాబాద్', + }, + ); + expect(waDailySalesBody).toContain('రోజువారీ అమ్మకాల నివేదిక'); + expect(waDailySalesBody).toContain('అమ్మకాల సారాంశం'); + expect(waDailySalesBody).toContain('నికర వసూళ్లు'); + expect(waDailySalesBody).toContain('చెల్లింపు విధానాలు'); + expect(waDailySalesBody).toContain('అగ్ర ఉత్పత్తులు'); + expect(waDailySalesBody).toContain('హైదరాబాదీ బిర్యానీ'); + + const dailySalesHtmlRes = await request.get( + `${E2E_BASE_URL}/api/reports/daily-sales/export?format=html`, + { headers }, + ); + expect(dailySalesHtmlRes.ok()).toBeTruthy(); + const dailySalesHtml = await dailySalesHtmlRes.text(); + expect(dailySalesHtml).toContain('Noto Sans Telugu'); + expect(dailySalesHtml).toContain('Kohinoor Telugu'); + + const dailyInvoicesHtmlRes = await request.get( + `${E2E_BASE_URL}/api/reports/daily-invoices/export?format=html`, + { headers }, + ); + expect(dailyInvoicesHtmlRes.ok()).toBeTruthy(); + const dailyInvoicesHtml = await dailyInvoicesHtmlRes.text(); + expect(dailyInvoicesHtml).toContain('Noto Sans Telugu'); + + fs.writeFileSync( + path.join(EVIDENCE_DIR, '08-whatsapp-reports-telugu.txt'), + waDailySalesBody, + 'utf8', + ); + + const waContext = await browser.newContext({ viewport: { width: 960, height: 800 } }); + const waPage = await waContext.newPage(); + await waPage.setContent(` + + + Telugu WhatsApp & Daily Sales Reports + +
${waDailySalesBody}
+
${dailySalesHtml}
+ + + `); + await expect(waPage.getByText('రోజువారీ అమ్మకాల నివేదిక').first()).toBeVisible(); + await expect(waPage.getByText('అమ్మకాల సారాంశం').first()).toBeVisible(); + await waPage.screenshot({ + path: path.join(EVIDENCE_DIR, '08-whatsapp-reports-telugu.png'), + fullPage: true, + }); + await waContext.close(); + } finally { + if (customerDisplayTokenId !== null) { + const revokeRes = await request.delete( + `${E2E_BASE_URL}/api/settings/customer-display/tokens/${customerDisplayTokenId}`, + { headers }, + ); + expect(revokeRes.ok()).toBeTruthy(); + } + const restoreLangRes = await request.put(`${E2E_BASE_URL}/api/settings/language`, { + headers, + data: { value: initialLanguage }, + }); + expect(restoreLangRes.ok()).toBeTruthy(); + await setLanguage(page, initialLanguage as 'en').catch(() => {}); + if (createdOrderIds.length > 0) { + const setPinRes = await request.put(`${E2E_BASE_URL}/api/staff/e2e-manager`, { + headers, + data: { pin: '1111' }, + }); + expect(setPinRes.ok()).toBeTruthy(); + try { + for (const orderId of createdOrderIds) { + const cancelRes = await request.patch(`${E2E_BASE_URL}/api/orders/${orderId}/status`, { + headers, + data: { + status: 'cancelled', + override_pin: '1111', + approver_id: 'e2e-manager', + }, + }); + expect(cancelRes.ok()).toBeTruthy(); + } + } finally { + const clearPinRes = await request.put(`${E2E_BASE_URL}/api/staff/e2e-manager`, { + headers, + data: { pin: null }, + }); + expect(clearPinRes.ok()).toBeTruthy(); + } + } + for (const prodId of createdProductIds) { + const delProdRes = await request.delete(`${E2E_BASE_URL}/api/products/${prodId}`, { + headers, + }); + expect(delProdRes.ok()).toBeTruthy(); + } + for (const catId of createdCategoryIds) { + const delCatRes = await request.delete(`${E2E_BASE_URL}/api/categories/${catId}`, { + headers, + }); + expect(delCatRes.ok()).toBeTruthy(); + } + } + }); +}); diff --git a/frontend/src/app/globals.css b/frontend/src/app/globals.css index 5fe0325bf..987a8dfb4 100644 --- a/frontend/src/app/globals.css +++ b/frontend/src/app/globals.css @@ -5,7 +5,7 @@ @custom-variant dark (&:is(.dark *)); :root { - --font-sans: "Geist", "Noto Sans Devanagari", "Nirmala UI", "Kohinoor Devanagari", "Devanagari Sangam MN", "Noto Sans Gurmukhi", "Raavi", "Kohinoor Gurmukhi", "Gurmukhi Sangam MN", system-ui, sans-serif; + --font-sans: "Geist", "Noto Sans Devanagari", "Nirmala UI", "Kohinoor Devanagari", "Devanagari Sangam MN", "Noto Sans Gurmukhi", "Raavi", "Kohinoor Gurmukhi", "Gurmukhi Sangam MN", "Noto Sans Telugu", "Kohinoor Telugu", "Telugu Sangam MN", system-ui, sans-serif; --font-mono: "Geist Mono", monospace; --radius: 0.625rem; --background: oklch(1 0 0); diff --git a/frontend/src/lib/i18n/languages.ts b/frontend/src/lib/i18n/languages.ts index 240cf0ae6..1e1074017 100644 --- a/frontend/src/lib/i18n/languages.ts +++ b/frontend/src/lib/i18n/languages.ts @@ -218,6 +218,13 @@ export const LANGUAGES = { selectable: true, load: () => import('./messages/pa.json'), }, + te: { + locale: 'te-IN', + nativeName: 'తెలుగు', + direction: 'ltr', + selectable: true, + load: () => import('./messages/te.json'), + }, } as const satisfies Record; export type Language = keyof typeof LANGUAGES; diff --git a/frontend/src/lib/i18n/messages/te.json b/frontend/src/lib/i18n/messages/te.json new file mode 100644 index 000000000..350623048 --- /dev/null +++ b/frontend/src/lib/i18n/messages/te.json @@ -0,0 +1,3601 @@ +{ + "addonGroups": { + "addCount": "{count, plural, one {# యాడ్-ఆన్} other {# యాడ్-ఆన్లు}}", + "addGroup": "గ్రూప్ జోడించు", + "addonAdded": "యాడ్-ఆన్ జోడించబడింది", + "addonDeleted": "యాడ్-ఆన్ తొలగించబడింది", + "addonUpdated": "యాడ్-ఆన్ అప్డేట్ చేయబడింది", + "deleteAddonConfirm": "ఈ యాడ్-ఆన్ తొలగించాలా?", + "deleteGroupConfirm": "ఈ యాడ్-ఆన్ గ్రూప్ మరియు దాని అన్ని యాడ్-ఆన్లను తొలగించాలా?", + "editGroup": "గ్రూప్ సవరించు", + "failedToAddAddon": "యాడ్-ఆన్ జోడించడం విఫలమైంది", + "failedToDeleteAddon": "యాడ్-ఆన్ తొలగించడం విఫలమైంది", + "failedToLoad": "యాడ్-ఆన్ గ్రూపులను లోడ్ చేయడం విఫలమైంది", + "failedToUpdateAddon": "యాడ్-ఆన్ అప్డేట్ చేయడం విఫలమైంది", + "groupCreated": "గ్రూప్ సృష్టించబడింది", + "groupDeleted": "గ్రూప్ తొలగించబడింది", + "groupUpdated": "గ్రూప్ అప్డేట్ చేయబడింది", + "minExceedsAvailable": "కనీస ఎంపిక అందుబాటులో ఉన్న యాడ్-ఆన్ల సంఖ్యను ({count}) మించకూడదు", + "minExceedsMax": "కనీస ఎంపిక గరిష్ట ఎంపికను మించకూడదు", + "noAddonGroups": "ఇంకా యాడ్-ఆన్ గ్రూపులు లేవు. మీ మొదటి గ్రూప్ సృష్టించండి!", + "selectRange": "{min}–{max} ఎంచుకోండి", + "title": "యాడ్-ఆన్ గ్రూపులు" + }, + "auth": { + "accountCreated": "ఖాతా విజయవంతంగా సృష్టించబడింది!", + "attemptsRemaining": "లాకౌట్ కావడానికి ముందు మిగిలిన ప్రయత్నాలు: {count}.", + "businessNameLabel": "వ్యాపారం పేరు", + "businessNamePlaceholder": "ఉదా., టేస్టీ బైట్స్ రెస్టారెంట్", + "confirmPassword": "పాస్వర్డ్ నిర్ధారించండి", + "connectionFailed": "సర్వర్ను చేరుకోవడం సాధ్యం కాలేదు. మీ కనెక్షన్ తనిఖీ చేసి మళ్లీ ప్రయత్నించండి.", + "countryIndia": "భారతదేశం", + "countryLabel": "దేశం", + "countryThailand": "థాయిలాండ్", + "createAccount": "ఖాతా సృష్టించండి", + "dbErrorPrefix": "డేటాబేస్ లోపం:", + "email": "ఈమెయిల్", + "emailPlaceholder": "you@business.com", + "forgotPasswordLink": "పాస్వర్డ్ మర్చిపోయారా? యాక్సెస్ పునరుద్ధరించండి", + "haveAccount": "ఇప్పటికే ఖాతా ఉందా?", + "invalidCredentials": "చెల్లని ఈమెయిల్ లేదా పాస్వర్డ్", + "lockedOut": "చాలా విఫల ప్రయత్నాలు జరిగాయి. {minutes} నిమిషాల్లో మళ్లీ ప్రయత్నించండి.", + "loginFailed": "లాగిన్ విఫలమైంది — డేటాబేస్లో లోపం ఉండవచ్చు.", + "password": "పాస్వర్డ్", + "passwordPlaceholder": "మీ పాస్వర్డ్ నమోదు చేయండి", + "passwordsDoNotMatch": "పాస్వర్డ్లు సరిపోలడం లేదు", + "passwordsMatch": "పాస్వర్డ్లు సరిపోలాయి", + "recoverBackToLogin": "సైన్ ఇన్కు తిరిగి వెళ్ళు", + "recoverMethodEmail": "ఈమెయిల్ లింక్", + "recoverMethodPin": "మాస్టర్ పిన్", + "recoverEmailIntro": "FloAdminలో నమోదు చేసిన యజమాని ఈమెయిల్ చిరునామాకు మేము రీసెట్ లింక్ పంపుతాము. దాన్ని ఆమోదించి, ఇక్కడ కొత్త పాస్వర్డ్ ఎంచుకోండి.", + "recoverEmailSend": "నాకు రీసెట్ లింక్ ఈమెయిల్ చేయండి", + "recoverEmailSending": "పంపుతోంది...", + "recoverEmailSent": "{email} తనిఖీ చేసి ఆమోదించడానికి లింక్పై క్లిక్ చేయండి. ఈ పేజీ స్వయంచాలకంగా అప్డేట్ అవుతుంది.", + "recoverEmailVerifying": "మీ యజమాని ఈమెయిల్ ఇంకా ధృవీకరించబడలేదు. మేము {email} కు ధృవీకరణ ఈమెయిల్ పంపాము. అందులోని లింక్పై క్లిక్ చేస్తే మేము స్వయంచాలకంగా రీసెట్ లింక్ పంపుతాము.", + "recoverEmailResend": "మళ్లీ పంపు", + "recoverEmailExpired": "ఈ రీసెట్ లింక్ గడువు ముగిసింది. కొత్తది పంపండి.", + "recoverEmailUnavailable": "FloAdminను చేరుకోవడం సాధ్యం కాలేదు. మీ కనెక్షన్ తనిఖీ చేయండి లేదా మాస్టర్ పిన్ ఉపయోగించండి.", + "recoverEmailRateLimited": "చాలా రీసెట్ అభ్యర్థనలు వచ్చాయి. తర్వాత మళ్లీ ప్రయత్నించండి.", + "recoverChecking": "ఈ పరికరంలో రికవరీ లభ్యతను తనిఖీ చేస్తోంది...", + "recoverConfirmPasswordLabel": "కొత్త పాస్వర్డ్ నిర్ధారించండి", + "recoverConfirmPasswordPlaceholder": "కొత్త పాస్వర్డ్ మళ్లీ నమోదు చేయండి", + "recoverErrorGeneric": "రికవరీ విఫలమైంది. దయచేసి మళ్లీ ప్రయత్నించండి.", + "recoverNewPasswordLabel": "కొత్త పాస్వర్డ్", + "recoverNewPasswordPlaceholder": "కొత్త పాస్వర్డ్ నమోదు చేయండి", + "recoverNoOwner": "ఈ ఇన్స్టాల్లో ఆ ఈమెయిల్తో యాక్టివ్ యజమాని ఖాతా కనుగొనబడలేదు.", + "recoverPasswordMismatch": "పాస్వర్డ్లు సరిపోలడం లేదు", + "recoverPasswordRequirements": "పాస్వర్డ్ కనీసం 4 అక్షరాల పొడవు ఉండాలి.", + "recoverPinFormat": "ఈ ఇన్స్టాల్ కోసం సెట్ చేసిన 4-అంకెల మాస్టర్ పిన్ నమోదు చేయండి.", + "recoverPinHint": "మొదటిసారి సెటప్ సమయంలో ఈ పరికరం కోసం సెట్ చేసిన 4-అంకెల మాస్టర్ పిన్.", + "recoverPinLabel": "మాస్టర్ పిన్", + "recoverPinUnavailable": "ఈ పరికరంలో మాస్టర్ పిన్ రక్షణ అందుబాటులో లేదు (OS కీరింగ్ లేదు), కాబట్టి ఇక్కడ స్థానిక పాస్వర్డ్ రికవరీ సాధ్యం కాదు. ఈ ఇన్స్టాల్ను పునరుద్ధరించడానికి సపోర్ట్ను సంప్రదించండి లేదా నేరుగా డేటాబేస్ యాక్సెస్ ఉపయోగించండి.", + "recoverRateLimited": "చాలా తప్పు మాస్టర్ పిన్ ప్రయత్నాలు. తర్వాత మళ్లీ ప్రయత్నించండి.", + "recoverSubmit": "పాస్వర్డ్ రీసెట్ చేయండి", + "recoverSubmitting": "రీసెట్ చేస్తోంది...", + "recoverSubtitle": "కొత్త పాస్వర్డ్ సెట్ చేయడానికి మీ ఈమెయిల్ మరియు ఈ పరికరం యొక్క మాస్టర్ పిన్ నమోదు చేయండి.", + "recoverSuccess": "పాస్వర్డ్ విజయవంతంగా రీసెట్ చేయబడింది. మీరు ఇప్పుడు సైన్ ఇన్ చేయవచ్చు.", + "recoverTitle": "యాక్సెస్ పునరుద్ధరించండి", + "recoverWrongPin": "చెల్లని మాస్టర్ పిన్.", + "registerSubtitle": "మీ ఖాతాను సృష్టించి మీ రెస్టారెంట్ను సెటప్ చేయండి", + "registrationFailed": "నమోదు విఫలమైంది", + "rememberMe": "నన్ను లాగిన్లో ఉంచు", + "selectBusiness": "వ్యాపారాన్ని ఎంచుకోండి", + "selectBusinessFailed": "వ్యాపారాన్ని ఎంచుకోవడం విఫలమైంది", + "selectBusinessHint": "నిర్వహించడానికి ఏ వ్యాపారాన్ని ఎంచుకోవాలో నిర్ణయించండి", + "signIn": "సైన్ ఇన్", + "signInSuccess": "లాగిన్ విజయవంతమైంది!", + "signInTitle": "మీ వ్యాపారాన్ని నిర్వహించడానికి సైన్ ఇన్ చేయండి", + "signingIn": "సైన్ ఇన్ అవుతోంది...", + "storageUnavailable": "మీ సెషన్ను సేవ్ చేయడం సాధ్యం కాలేదు. మీ బ్రౌజర్ స్టోరేజ్ను బ్లాక్ చేస్తూ ఉండవచ్చు (ప్రైవేట్ మోడ్ లేదా డిసేబుల్ చేసిన కుకీలు).", + "yourName": "మీ పేరు", + "quickSwitchTitle": "త్వరిత మార్పు", + "quickSwitchSubtitle": "మీ పిన్తో సైన్ ఇన్ చేయడానికి మీ ప్రొఫైల్ ఎంచుకోండి", + "enterPinFor": "{name} కోసం పిన్ నమోదు చేయండి" + }, + "backup": { + "creating": "బ్యాకప్ సృష్టిస్తోంది...", + "failedWith": "బ్యాకప్ విఫలమైంది: {error}", + "savedTo": "{path} లో బ్యాకప్ సేవ్ చేయబడింది" + }, + "businessType": { + "restaurant": "రెస్టారెంట్" + }, + "common": { + "active": "యాక్టివ్", + "add": "జోడించు", + "amount": "మొత్తం", + "appDescription": "రెస్టారెంట్ల కోసం స్మార్ట్ పాయింట్ ఆఫ్ సేల్", + "appTitle": "Flo", + "brandName": "Flo Cafe", + "businessNameFallback": "స్టోర్", + "cancel": "రద్దు", + "checkPrinterConnection": "ప్రింటర్ కనెక్షన్ తనిఖీ చేయండి", + "close": "మూసివేయి", + "confirm": "నిర్ధారించు", + "continue": "కొనసాగించు", + "create": "సృష్టించు", + "created": "సృష్టించబడింది:", + "delete": "తొలగించు", + "discount": "తగ్గింపు", + "done": "పూర్తయింది", + "downloadFailed": "డౌన్లోడ్ విఫలమైంది", + "edit": "సవరించు", + "failedToDelete": "తొలగించడం విఫలమైంది", + "failedToSave": "సేవ్ చేయడం విఫలమైంది", + "import": "దిగుమతి", + "importFailed": "దిగుమతి విఫలమైంది", + "inactive": "ఇనాక్టివ్", + "justNow": "ఇప్పుడే", + "loading": "లోడ్ అవుతోంది...", + "loadingScreen": "లోడ్ అవుతోంది...", + "logoAlt": "Flo Cafe", + "maximize": "పెద్దది చేయి", + "menu": "మెనూ", + "minimize": "చిన్నది చేయి", + "more": "మరిన్ని", + "namePlaceholder": "పేరు", + "no": "కాదు", + "notAvailable": "అందుబాటులో లేదు", + "optional": "ఐచ్ఛికం", + "or": "లేదా", + "percentage": "శాతం", + "pricePlaceholder": "ధర", + "print": "ప్రింట్", + "reasonOptional": "కారణం (ఐచ్ఛికం)", + "remove": "తీసివేయి", + "removeItem": "ఐటెమ్ తీసివేయి", + "reprint": "రీప్రింట్", + "restore": "పునరుద్ధరించు", + "reviewFix": "సమీక్షించి సరిచేయి", + "save": "సేవ్ చేయి", + "saveFailed": "సేవ్ చేయడం సాధ్యం కాలేదు. మళ్లీ ప్రయత్నించండి.", + "saving": "సేవ్ అవుతోంది...", + "search": "వెతుకు", + "sendViaFlo": "Flo ద్వారా పంపు", + "shareViaWhatsApp": "WhatsApp ద్వారా షేర్ చేయి", + "skipped": "దాటవేయబడింది (ఇప్పటికే ఉంది):", + "somethingWrong": "ఏదో తప్పు జరిగింది", + "subtotal": "ఉప మొత్తం", + "tableFallback": "టేబుల్", + "timeHoursMinutes": "{h}గం {m}ని", + "timeHoursMinutesAgo": "{h}గం {m}ని క్రితం", + "timeMinutes": "{m}ని", + "timeMinutesAgo": "{m}ని క్రితం", + "total": "మొత్తం", + "unknown": "తెలియదు", + "update": "అప్డేట్", + "windowControls": "విండో నియంత్రణలు", + "yes": "అవును", + "back": "వెనుకకు", + "tax": "పన్ను", + "loadMore": "మరిన్ని లోడ్ చేయి", + "clear": "క్లియర్ చేయి", + "noResults": "సరిపోయే ఫలితాలు లేవు" + }, + "countries": { + "selectCountry": "దేశాన్ని ఎంచుకోండి…" + }, + "customer": { + "add": "కస్టమర్ జోడించు", + "added": "కస్టమర్ జోడించబడ్డారు", + "edit": "కస్టమర్ సవరించు", + "email": "ఈమెయిల్", + "ledgerLoadFailed": "లాయల్టీ లెడ్జర్ లోడ్ చేయడం విఫలమైంది", + "loadFailed": "కస్టమర్లను లోడ్ చేయడం విఫలమైంది", + "loadingLedger": "లోడ్ అవుతోంది...", + "loyalty": "లాయల్టీ", + "name": "పేరు", + "phone": "ఫోన్", + "ptsSuffix": "పాయింట్లు", + "saveFailed": "సేవ్ చేయడం విఫలమైంది", + "search": "పేరు, ఫోన్ లేదా ఈమెయిల్ ద్వారా వెతకండి…", + "totalSpent": "మొత్తం ఖర్చు", + "update": "అప్డేట్", + "updated": "కస్టమర్ అప్డేట్ చేయబడ్డారు", + "viewLedgerTitle": "లాయల్టీ లెడ్జర్ చూడండి", + "visits": "సందర్శనలు" + }, + "customers": { + "actionRequired": "చర్య అవసరం", + "billingHistory": "బిల్లింగ్ చరిత్ర", + "columnActions": "చర్యలు", + "columnAmount": "మొత్తం", + "columnBill": "బిల్లు", + "columnCustomer": "కస్టమర్", + "columnDate": "తేదీ", + "columnDescription": "వివరణ", + "columnEarned": "సంపాదించినవి", + "columnExpires": "గడువు ముగింపు", + "columnLastVisit": "చివరి సందర్శన", + "columnLedger": "లెడ్జర్", + "columnPoints": "పాయింట్లు", + "columnRedeemed": "రిడీమ్ చేసినవి", + "empty": "కస్టమర్లు ఎవరూ కనుగొనబడలేదు", + "first200": "మొదటి 200 మంది కస్టమర్లను చూపిస్తోంది — మరిన్ని చూడటానికి మీ శోధనను మెరుగుపరచండి.", + "invalidPhoneCount": "{count, plural, one {# కస్టమర్కు చెల్లని లేదా పాత ఫోన్ నంబర్ ఫార్మాట్ ఉంది.} other {# మంది కస్టమర్లకు చెల్లని లేదా పాత ఫోన్ నంబర్ ఫార్మాట్ ఉంది.}}", + "loyaltyLedger": "లాయల్టీ లెడ్జర్", + "noBills": "ఇంకా బిల్లులు లేవు", + "noTransactions": "ఇంకా లావాదేవీలు లేవు", + "pointsHistory": "పాయింట్ల చరిత్ర", + "totalBalance": "మొత్తం బ్యాలెన్స్", + "totalPointsEarned": "సంపాదించిన పాయింట్లు", + "totalPointsRedeemed": "రిడీమ్ చేసిన పాయింట్లు" + }, + "customerDisplay": { + "orderStatus": "ఆర్డర్ స్థితి", + "preparingTitle": "సిద్ధమవుతోంది", + "preparingHint": "మేము మీ ఆర్డర్ను సిద్ధం చేస్తున్నాము", + "readyTitle": "పికప్ కోసం సిద్ధంగా ఉంది", + "readyHint": "దయచేసి మీ ఆర్డర్ను తీసుకోండి", + "orderLabel": "ఆర్డర్", + "noPreparing": "ప్రస్తుతం ఏ ఆర్డర్లు సిద్ధం కావడం లేదు", + "noReady": "ఇంకా ఏ ఆర్డర్లు సిద్ధంగా లేవు", + "loadingOrders": "ఆర్డర్లు లోడ్ అవుతున్నాయి…", + "connecting": "కనెక్ట్ అవుతోంది…", + "connectionProblem": "కనెక్షన్ సమస్య — మళ్లీ ప్రయత్నిస్తోంది…", + "staleData": "కనెక్షన్ పోయింది. చివరిగా అందుబాటులో ఉన్న ఆర్డర్లను చూపిస్తోంది.", + "updatedAt": "{time} కి అప్డేట్ చేయబడింది", + "settingsTitle": "కస్టమర్ డిస్ప్లే", + "settingsHint": "కస్టమర్ చూసే ఆర్డర్ స్థితి బోర్డులో ఏ ఆర్డర్లు కనిపించాలో ఎంచుకోండి.", + "statusesLabel": "చూపించే ఆర్డర్ స్థితులు", + "statusPending": "పెండింగ్", + "statusPreparing": "సిద్ధమవుతోంది", + "statusReady": "సిద్ధంగా ఉంది", + "refreshLabel": "రిఫ్రెష్ విరామం (సెకన్లు)", + "showUpdatedLabel": "చివరిగా అప్డేట్ చేసిన సమయాన్ని చూపించు", + "urlLabel": "డిస్ప్లే చిరునామా", + "copyUrl": "చిరునామా కాపీ చేయి", + "urlCopied": "చిరునామా కాపీ చేయబడింది", + "openDisplay": "డిస్ప్లే తెరువు", + "saved": "కస్టమర్ డిస్ప్లే సెట్టింగ్లు సేవ్ చేయబడ్డాయి", + "saveFailed": "కస్టమర్ డిస్ప్లే సెట్టింగ్లను సేవ్ చేయడం సాధ్యం కాలేదు", + "atLeastOneStatus": "కనీసం ఒక స్థితిని ఎంచుకోండి", + "pairedTitle": "జత చేసిన డిస్ప్లేలు", + "pairedHint": "సిబ్బంది లాగిన్ లేకుండా బోర్డును చూపించడానికి టీవీ లేదా టాబ్లెట్ను జత చేయండి. జత చేసిన పరికరం ఆర్డర్ నంబర్లు మరియు స్థితులను మాత్రమే చూడగలదు.", + "primaryLanAddress": "ప్రాథమిక LAN చిరునామా", + "otherAddresses": "ఇతర చిరునామాలను చూపించు", + "localPreviewAddress": "ఈ కంప్యూటర్ మాత్రమే (స్థానిక ప్రివ్యూ)", + "lanPairingUnavailable": "LAN జత చేయడం అందుబాటులో లేదు. ఈ కంప్యూటర్ను మాత్రమే ఉపయోగించడానికి స్థానిక ప్రివ్యూను ఎంచుకోండి.", + "networkInfoLoadFailed": "నెట్వర్క్ చిరునామాలను లోడ్ చేయడం సాధ్యం కాలేదు.", + "pairLabel": "డిస్ప్లే పేరు", + "pairLabelPlaceholder": "ఉదా. కౌంటర్ టీవీ", + "pairCreate": "డిస్ప్లే జత చేయి", + "pairedEmpty": "ఇంకా ఏ డిస్ప్లేలు జత చేయబడలేదు", + "pairedLastSeen": "చివరిగా కనిపించింది {time}", + "pairedNeverSeen": "ఇంకా కనెక్ట్ కాలేదు", + "pairedLinkTitle": "డిస్ప్లేలో ఈ లింక్ను తెరవండి", + "pairedLinkOnce": "ఇప్పుడే కాపీ చేయండి — ఇది మళ్లీ చూపించబడదు.", + "revoke": "రద్దు చేయి", + "revoked": "డిస్ప్లే రద్దు చేయబడింది", + "revokeFailed": "డిస్ప్లేను రద్దు చేయడం సాధ్యం కాలేదు", + "pairFailed": "డిస్ప్లేను జత చేయడం సాధ్యం కాలేదు", + "tokenLimit": "మరొకటి జత చేసే ముందు ఉపయోగించని డిస్ప్లేను రద్దు చేయండి", + "unpairedTitle": "ఈ డిస్ప్లే జత చేయబడలేదు", + "unpairedHint": "కొత్త జత చేసే లింక్ కోసం మేనేజర్ను అడగండి." + }, + "dashboard": { + "aov": "సగటు ఆర్డర్ విలువ", + "avgPrepTime": "సగటు తయారీ సమయం", + "avgTableTurn": "సగటు టేబుల్ మార్పు", + "billsCollected": "వసూలు చేసిన బిల్లులు", + "busiestDay": "అత్యంత రద్దీ రోజు", + "busiestHour": "అత్యంత రద్దీ గంట", + "businessPatterns": "వ్యాపార సరళి", + "businessPatternsHint": "గత {days} రోజుల ఆధారంగా", + "categoryQuantitySold": "{quantity} అమ్ముడయ్యాయి", + "collectedAt": "వసూలు చేసినది {date}", + "day": "రోజు", + "grossCollections": "స్థూల వసూళ్లు", + "idlestDay": "అత్యంత తక్కువ రద్దీ రోజు", + "idlestHour": "అత్యంత తక్కువ రద్దీ గంట", + "minutesValue": "{minutes}ని", + "month": "నెల", + "range": "పరిధి", + "monthOrders": "నెల ఆర్డర్లు", + "netCollections": "నికర వసూళ్లు", + "newCustomers": "కొత్త కస్టమర్లు", + "noOrdersYet": "ఇంకా ఆర్డర్లు లేవు", + "noPaymentsYet": "ఇంకా చెల్లింపులు వసూలు కాలేదు", + "noRefunds": "ఈ నెలకు సంబంధించిన రీఫండ్లు లేవు", + "noSalesYet": "ఈరోజు ఇంకా అమ్మకాలు లేవు", + "notEnoughData": "ఇంకా తగినంత డేటా లేదు", + "openDatePicker": "తేదీ పికర్ తెరువు", + "openMonthPicker": "నెల పికర్ తెరువు", + "orders": "ఆర్డర్లు", + "ordersCount": "ఆర్డర్లు: {count}", + "paymentMethodCount": "{count} చెల్లింపులు · {percent}%", + "paymentMethods": "చెల్లింపు విధానాలు", + "periodView": "డ్యాష్బోర్డ్ వ్యవధి", + "pendingOrders": "పెండింగ్ ఆర్డర్లు", + "productSoldOrders": "{quantity} అమ్ముడయ్యాయి · {orders} ఆర్డర్లు", + "recentOrders": "ఇటీవలి ఆర్డర్లు", + "refundActivity": "రీఫండ్ కార్యకలాపాలు", + "refundActivityHint": "రీఫండ్లు వాటి చెల్లింపు వసూలు చేసిన నెలలో చూపబడతాయి.", + "refundApproved": "{name} ఆమోదించారు", + "refundCount": "రీఫండ్ల సంఖ్య", + "refundReference": "బిల్లు {bill} · ఆర్డర్ {order}", + "refundedAt": "రీఫండ్ చేసినది {date}", + "refunds": "రీఫండ్లు", + "runningOrders": "నడుస్తున్న ఆర్డర్లు", + "sales": "అమ్మకాలు", + "selectDate": "తేదీ ఎంచుకోండి", + "selectMonth": "నెల ఎంచుకోండి", + "staffOrderCount": "ఆర్డర్లు: {orders}", + "tablesOccupied": "ఆక్రమించిన టేబుళ్లు", + "title": "డ్యాష్బోర్డ్", + "todaySales": "నేటి అమ్మకాలు", + "topCategories": "అగ్ర వర్గాలు", + "topProducts": "అగ్ర ఉత్పత్తులు", + "topProductsMonth": "ఈ నెల అగ్ర ఉత్పత్తులు", + "topProductsToday": "నేటి అగ్ర ఉత్పత్తులు", + "topStaff": "అగ్ర సిబ్బంది", + "viewAll": "అన్నీ చూడండి", + "walkIn": "వాక్-ఇన్", + "closeShift": "రోజు ముగించు", + "openShift": "షిఫ్ట్ తెరువు", + "openShiftHint": "షిఫ్ట్ ప్రారంభించడానికి డ్రాయర్లోని నగదును లెక్కించండి.", + "closeShiftSession": "షిఫ్ట్ ముగించు", + "shiftOpened": "షిఫ్ట్ తెరవబడింది", + "shiftClosed": "షిఫ్ట్ ముగించబడింది", + "cashMovement": "నగదు లావాదేవీ", + "exportSales": "అమ్మకాలను ఎగుమతి చేయి", + "exportXlsx": "Excel (.xlsx)", + "exportCsv": "CSV (.csv)", + "exportPdf": "PDF (.pdf)", + "exportInvoicesPdf": "ఇన్వాయిస్లు (PDF)", + "exportCsvHint": "CSV ఐదు ఫైళ్లను డౌన్లోడ్ చేస్తుంది: సారాంశం, రోజువారీ, పన్నులు, ఐటెమ్లు మరియు చెల్లింపులు.", + "exportCsvStarted": "సారాంశం, రోజువారీ, పన్నులు, ఐటెమ్లు మరియు చెల్లింపుల CSV ఫైళ్లు డౌన్లోడ్ అవుతున్నాయి…", + "exportCustomerSales": "కస్టమర్ అమ్మకాలు", + "liveNow": "ఇప్పుడు లైవ్", + "kpiChangeVsSameDayLastWeek": "గత వారం ఇదే రోజుతో పోలిస్తే {percent}%", + "kpiNewVsSameDayLastWeek": "గత వారం ఇదే రోజుతో పోలిస్తే కొత్తది", + "kpiNoChangeVsSameDayLastWeek": "గత వారం ఇదే రోజుతో పోలిస్తే మార్పు లేదు", + "cashMovementHint": "డ్రాయర్లో వేసిన లేదా తీసిన డబ్బును నమోదు చేయండి.", + "movementType": "లావాదేవీ రకం", + "payIn": "నగదు జమ", + "payOut": "నగదు ఉపసంహరణ", + "safeDrop": "సేఫ్ డ్రాప్", + "movementAmount": "మొత్తం", + "movementAmountRequired": "చెల్లబాటు అయ్యే మొత్తాన్ని నమోదు చేయండి.", + "movementReason": "కారణం", + "movementReasonRequired": "ఈ లావాదేవీకి కారణం అవసరం.", + "recordMovement": "లావాదేవీ నమోదు చేయి", + "movementSaved": "నగదు లావాదేవీ నమోదు చేయబడింది", + "movementSaveFailed": "నగదు లావాదేవీని నమోదు చేయడం సాధ్యం కాలేదు", + "movementHistory": "లావాదేవీ చరిత్ర", + "noMovements": "ఈ రోజుకు నగదు లావాదేవీలు లేవు", + "voidMovement": "లావాదేవీ రద్దు చేయి", + "voidReason": "రద్దు కారణం", + "movementVoided": "నగదు లావాదేవీ రద్దు చేయబడింది", + "voided": "రద్దు చేయబడింది", + "xReport": "X నివేదిక", + "zReport": "Z నివేదిక", + "openingFloat": "ప్రారంభ నగదు", + "expectedCash": "ఆశించిన నగదు", + "expectedCashWithMovements": "ఆశించిన నగదు (అమ్మకాలు మరియు లావాదేవీలు)", + "closureNotes": "గమనికలు", + "countedCash": "లెక్కించిన నగదు", + "variance": "తేడా", + "varianceExact": "ఖచ్చితంగా సరిపోయింది", + "varianceShort": "తక్కువ", + "varianceOver": "ఎక్కువ", + "printZReport": "Z ప్రింట్ చేయి", + "reprintZ": "Z రీప్రింట్ చేయి", + "reprintAddsMarker": "రీప్రింట్ ఒక రీప్రింట్ లైన్ను జోడిస్తుంది", + "closeAnotherDay": "మరో రోజు ముగించు", + "alreadyClosed": "ఈ రోజు ఇప్పటికే ముగించబడింది", + "noPriorCloseHint": "మునుపటి రోజు ముగించబడలేదు — ప్రారంభ నగదు డిఫాల్ట్గా 0", + "billsCount": "బిల్లులు: {count}", + "businessDateLabel": "వ్యాపార తేదీ", + "periodWindow": "వ్యవధి: {start} నుండి {end} వరకు", + "periodStart": "వ్యవధి ప్రారంభం", + "periodEnd": "వ్యవధి ముగింపు", + "ticketCount": "సంఖ్య", + "ticketOperatorSignature": "ఆపరేటర్ సంతకం", + "ticketSectionPayments": "చెల్లింపు విధానాలు", + "ticketSectionCashMovements": "నగదు లావాదేవీలు", + "ticketSectionRefunds": "రీఫండ్లు", + "ticketSectionTax": "పన్ను వివరాలు", + "ticketSectionStaff": "సిబ్బంది అమ్మకాలు", + "ticketSectionOperator": "మూసివేసినవారు", + "ticketSectionNotes": "గమనికలు", + "ticketMethodCount": "{count} ×", + "ticketRefundCount": "× {count} రీఫండ్లు", + "ticketNoRefunds": "రీఫండ్లు లేవు", + "ticketNoTax": "పన్ను లేదు", + "ticketNoStaff": "సిబ్బంది అమ్మకాలు లేవు", + "ticketClosedAt": "{date} న ముగించబడింది", + "ticketFooter": "FloCafe ద్వారా రూపొందించబడింది", + "closeFlowLabel": "రోజు ముగింపు దశలు", + "closeStepReview": "సమీక్ష", + "closeStepCount": "లెక్కింపు", + "closeStepDone": "ముగించు", + "xReportSales": "నేటి అమ్మకాలు", + "refundsCount": "రీఫండ్లు: {count}", + "ticketNoPayments": "ఈ రోజుకు చెల్లింపులు లేవు", + "shiftLoadFailed": "షిఫ్ట్ స్థితిని లోడ్ చేయడం సాధ్యం కాలేదు.", + "sendViaWhatsApp": "WhatsApp కు పంపు", + "sendWhatsAppTitle": "WhatsApp కు నివేదిక పంపు", + "recipientPhone": "గ్రహీత ఫోన్ నంబర్", + "reportSentSuccess": "నివేదిక WhatsApp కు విజయవంతంగా పంపబడింది", + "reportSubmittedPending": "నివేదిక WhatsApp కు సమర్పించబడింది; డెలివరీ నిర్ధారణ కోసం వేచి ఉంది", + "reportOpeningWhatsAppWeb": "నివేదికతో WhatsApp తెరుస్తోంది...", + "salesSummary": "అమ్మకాల సారాంశం", + "paymentBreakdown": "చెల్లింపులు", + "drawerReconciliation": "డ్రాయర్ సరిపోలిక", + "priceExceptions": "ధర మినహాయింపులు", + "priceExceptionsEmpty": "ఈ వ్యవధిలో ధర మార్పులు లేవు", + "priceExceptionsCount": "ధర మార్పులు: {count}", + "priceExceptionsComps": "కాంప్లిమెంటరీ: {count}", + "priceExceptionsTotal": "మొత్తం తేడా: {amount}", + "priceExceptionOrder": "ఆర్డర్", + "priceExceptionItem": "ఐటెమ్", + "priceExceptionOriginal": "మెనూ ధర", + "priceExceptionBilled": "బిల్లు ధర", + "priceExceptionDifference": "తేడా", + "priceExceptionBy": "మార్చినవారు", + "priceExceptionAt": "ఎప్పుడు", + "priceExceptionReason": "కారణం", + "priceExceptionsAllShifts": "మొత్తం వ్యవధి", + "priceExceptionsShift": "షిఫ్ట్", + "priceExceptionsShiftOpen": "ఓపెన్", + "dayCloseOpenShiftBlocks": "ఈ వ్యాపార రోజును ముగించే ముందు ఓపెన్ షిఫ్ట్ #{id} ({name}) ను ముగించండి.", + "dayCloseOpenShiftBlocksGeneric": "ఈ రోజును ముగించే ముందు ఈ వ్యాపార రోజుకు సంబంధించిన ఓపెన్ షిఫ్ట్ను ముగించండి.", + "ingredientCost": "పదార్థాల ఖర్చు", + "grossProfit": "స్థూల లాభం", + "grossMargin": "స్థూల మార్జిన్", + "costUnknown": "ఖర్చు తెలియదు", + "partialCost": "పాక్షిక ఖర్చు", + "ingredientCostLabel": "ఖర్చు: {amount}", + "profitMarginLabel": "లాభం: {profit} ({margin})", + "dailySalesWhatsAppTitle": "రోజువారీ అమ్మకాల నివేదిక" + }, + "expenses": { + "addTitle": "ఖర్చు జోడించు", + "detailTitle": "ఖర్చు వివరాలు", + "replaceTitle": "ఖర్చు భర్తీ చేయి", + "voidTitle": "ఖర్చు రద్దు చేయి", + "paymentTitle": "చెల్లింపు నమోదు చేయి", + "reversalTitle": "చెల్లింపు వెనక్కి తీసుకో", + "category": "వర్గం", + "newCategory": "కొత్త వర్గం", + "categoryName": "వర్గం పేరు", + "payee": "చెల్లింపు గ్రహీత", + "notes": "గమనికలు", + "incurredOn": "ఖర్చయిన తేదీ", + "status": "స్థితి", + "statusVoided": "రద్దు చేయబడింది", + "statusReplaced": "భర్తీ చేయబడింది", + "from": "నుండి", + "to": "వరకు", + "currency": "కరెన్సీ", + "allCurrencies": "అన్ని కరెన్సీలు", + "incurred": "ఖర్చయినది", + "paidToDate": "ఇప్పటివరకు చెల్లించినది", + "due": "బకాయి", + "netPaid": "నికర చెల్లింపు", + "summaryBasis": "మొత్తాలు ఎంచుకున్న వ్యవధిలో జరిగిన ఖర్చులను చూపుతాయి; ఇప్పటివరకు చెల్లించినది నేటి వరకు ఉంటుంది. ఇది లాభం కాదు, మరియు క్యాష్ ఫ్లో కాదు.", + "openDetail": "వివరాలు", + "empty": "ఈ ఫిల్టర్లకు సరిపోయే ఖర్చులు లేవు.", + "recordedBy": "నమోదు చేసినవారు", + "recordedAt": "నమోదు చేసినది", + "payments": "చెల్లింపులు మరియు రివర్సల్స్", + "noPayments": "ఇంకా చెల్లింపులు నమోదు చేయబడలేదు.", + "method": "విధానం", + "methodBankTransfer": "బ్యాంక్ బదిలీ", + "methodOther": "ఇతర", + "reference": "రిఫరెన్స్", + "cashNotice": "నగదు చెల్లింపులు యాక్టివ్ డ్రాయర్ నుండి చెల్లించిన డబ్బును నమోదు చేస్తాయి మరియు నగదు ఉపసంహరణను సృష్టిస్తాయి.", + "cashSessionClosed": "ఏ షిఫ్ట్ తెరిచి లేదు. నగదు చెల్లింపు కోసం షిఫ్ట్ తెరవండి, లేదా నగదు యేతర విధానాన్ని నమోదు చేయండి.", + "cashUnavailable": "నగదు చెల్లింపును నమోదు చేయడానికి క్యాష్ డ్రాయర్ అనుమతి అవసరం.", + "reviewPayment": "{method} ద్వారా చెల్లించిన {amount} ను నమోదు చేస్తోంది.", + "reversalConfirm": "{method} ద్వారా చెల్లించిన {amount} ను రివర్స్ చేస్తుంది. అసలు చెల్లింపు లెడ్జర్లోనే ఉంటుంది.", + "cashAck": "నగదు నేటి డ్రాయర్లోకి తిరిగి వచ్చింది.", + "cashAckRequired": "నగదు నేటి డ్రాయర్లోకి తిరిగి వచ్చిందని నిర్ధారించండి.", + "cashReversalNotice": "నగదు రివర్సల్ నేటి డ్రాయర్లోకి తిరిగి వచ్చే డబ్బును నమోదు చేస్తుంది మరియు నగదు జమను సృష్టిస్తుంది.", + "voidConsequence": "రద్దు చేయడం వల్ల ఖర్చు చరిత్రలో కనిపిస్తుంది కానీ యాక్టివ్ మొత్తాల నుండి తీసివేయబడుతుంది.", + "replaceConsequence": "భర్తీ చేయడం వల్ల ఈ ఖర్చు రద్దు చేయబడి అదే దశలో సరిదిద్దిన ఖర్చు సృష్టించబడుతుంది.", + "blockedByPayments": "ఈ ఖర్చును రద్దు చేసే లేదా భర్తీ చేసే ముందు ప్రతి చెల్లింపును రివర్స్ చేయండి.", + "reasonRequired": "కారణాన్ని నమోదు చేయండి.", + "amountRequired": "సున్నా కంటే ఎక్కువ మొత్తాన్ని నమోదు చేయండి.", + "descriptionRequired": "వివరణను నమోదు చేయండి.", + "categoryRequired": "వర్గాన్ని ఎంచుకోండి.", + "dateRequired": "ఖర్చు జరిగిన తేదీని ఎంచుకోండి.", + "exceedsDue": "మొత్తం ఇంకా బకాయి ఉన్న {amount} కంటే ఎక్కువ ఉండకూడదు.", + "attemptNotice": "మునుపటి సమర్పణకు సమాధానం రాలేదు. మరేదైనా చేసే ముందు అసలు సమర్పణను మళ్లీ ప్రయత్నించండి.", + "attemptRetry": "అసలు సమర్పణను మళ్లీ ప్రయత్నించు", + "attemptStorageBlocked": "ఈ పరికరం కొత్త ఖర్చు సమర్పణను సురక్షితంగా నిల్వ చేయలేదు, కాబట్టి ఏదీ పంపబడలేదు. మునుపటి ప్రయత్నాన్ని పరిష్కరించండి లేదా బ్రౌజర్ స్టోరేజ్ను ఖాళీ చేసి మళ్లీ ప్రయత్నించండి.", + "loadFailed": "ఖర్చులను లోడ్ చేయడం సాధ్యం కాలేదు.", + "detailLoadFailed": "ఈ ఖర్చును లోడ్ చేయడం సాధ్యం కాలేదు.", + "saveFailed": "ఖర్చును సేవ్ చేయడం సాధ్యం కాలేదు.", + "createdNotice": "ఖర్చు సృష్టించబడింది. చెల్లించినప్పుడు చెల్లింపును విడిగా నమోదు చేయండి.", + "addCategoryFailed": "వర్గాన్ని సృష్టించడం సాధ్యం కాలేదు.", + "voidedNotice": "ఖర్చు రద్దు చేయబడింది.", + "replacedNotice": "ఖర్చు భర్తీ చేయబడింది.", + "permissionDenied": "ఖర్చులను చూడటానికి మీకు అనుమతి లేదు.", + "description": "వివరణ", + "paymentRecorded": "చెల్లింపు నమోదు చేయబడింది.", + "reversalRecorded": "చెల్లింపు రివర్స్ చేయబడింది." + }, + "inventory": { + "tabSupplies": "సరఫరాలు", + "tabRecipes": "రెసిపీలు", + "tabMovements": "లావాదేవీలు", + "addSupply": "సరఫరా జోడించు", + "editSupply": "సరఫరా సవరించు", + "addRecipe": "రెసిపీ సృష్టించు", + "editRecipe": "రెసిపీ సవరించు", + "supplyName": "పేరు", + "baseUnit": "బేస్ యూనిట్", + "stock": "స్టాక్", + "threshold": "తక్కువ స్టాక్ పరిమితి", + "actions": "చర్యలు", + "lowStockOnly": "తక్కువ స్టాక్ మాత్రమే", + "includeInactive": "ఇనాక్టివ్ వాటిని చేర్చు", + "lowStock": "తక్కువ స్టాక్", + "emptySupplies": "ఇంకా సరఫరాలు లేవు", + "emptyRecipes": "ఇంకా రెసిపీలు లేవు", + "emptyMovements": "ఇంకా లావాదేవీలు లేవు", + "recordMovement": "లావాదేవీ నమోదు చేయి", + "receive": "స్వీకరించు", + "count": "లెక్కింపు", + "adjustment": "సర్దుబాటు", + "waste": "వృథా", + "recipeDepletion": "రెసిపీ వినియోగం", + "recipeRestore": "రెసిపీ పునరుద్ధరణ", + "movementType": "రకం", + "quantity": "పరిమాణం", + "stockAfter": "తర్వాత స్టాక్", + "reason": "కారణం", + "actor": "చేసినవారు", + "date": "తేదీ", + "supply": "సరఫరా", + "loadMore": "మరిన్ని లోడ్ చేయి", + "product": "ఉత్పత్తి", + "yield": "దిగుబడి", + "components": "భాగాలు", + "addComponent": "భాగం జోడించు", + "noAccess": "ఇన్వెంటరీ నిర్వహణకు మీకు యాక్సెస్ లేదు.", + "loadFailed": "ఇన్వెంటరీ లోడ్ చేయడం విఫలమైంది", + "saveFailed": "సేవ్ చేయడం విఫలమైంది", + "deleteFailed": "తొలగించడం విఫలమైంది", + "confirmDeleteSupply": "{name} సరఫరాను తొలగించాలా? దాని లావాదేవీ చరిత్ర అలాగే ఉంచబడుతుంది.", + "confirmDeleteRecipe": "{name} కోసం రెసిపీని తొలగించాలా?", + "unitCost": "యూనిట్ ఖర్చు", + "totalBatchCost": "మొత్తం బ్యాచ్ ఖర్చు", + "recipeCost": "రెసిపీ ఖర్చు", + "costUnknown": "ఖర్చు తెలియదు" + }, + "kds": { + "addonsLabel": "యాడ్-ఆన్లు", + "authFailed": "ధృవీకరణ విఫలమైంది", + "backTo": "తిరిగి {status} కి", + "bump": "బంప్", + "connectionConnecting": "కనెక్ట్ అవుతోంది...", + "connectionLive": "లైవ్", + "connectionPolling": "పోలింగ్ 5సె", + "deliveredDone": "✓ డెలివరీ చేయబడింది — తదుపరి చర్యలు లేవు", + "disabledHint": "ఈ వ్యాపారం కిచెన్ డిస్ప్లే సిస్టమ్ను ఆఫ్ చేసింది. సెట్టింగ్ల నుండి దాన్ని మళ్లీ ఆన్ చేయమని యజమానిని లేదా మేనేజర్ను అడగండి.", + "disabledHintDashboard": "ఈ వ్యాపారం కిచెన్ డిస్ప్లే సిస్టమ్ను ఆఫ్ చేసింది. యజమాని లేదా మేనేజర్ సెట్టింగ్ల నుండి దాన్ని మళ్లీ ఆన్ చేయవచ్చు.", + "disabledTitle": "కిచెన్ డిస్ప్లే నిలిపివేయబడింది", + "emptyAll": "యాక్టివ్ ఆర్డర్లు లేవు 🎉", + "emptyColumn": "—", + "emptyHint": "ఐటెమ్ల స్థితి మారినప్పుడు అవి ఇక్కడ కనిపిస్తాయి", + "emptyItems": "{status} ఐటెమ్లు లేవు", + "failedToUpdateItem": "ఐటెమ్ అప్డేట్ చేయడం విఫలమైంది", + "goToSettings": "సెట్టింగ్లకు వెళ్ళు", + "guestCount": "{count, plural, one {· # అతిథి} other {· # మంది అతిథులు}}", + "itemMarked": "ఐటెమ్ {status} గా గుర్తించబడింది", + "itemVoidedLocked": "ఈ ఐటెమ్ రద్దు చేయబడింది మరియు ఇకపై అప్డేట్ చేయబడదు.", + "itemsUpdateFailed": "{count, plural, one {# ఐటెమ్ను అప్డేట్ చేయడం సాధ్యం కాలేదు} other {# ఐటెమ్లను అప్డేట్ చేయడం సాధ్యం కాలేదు}}. బోర్డు రిఫ్రెష్ చేయబడింది.", + "loginFailed": "లాగిన్ విఫలమైంది", + "loginHint": "చెఫ్, మేనేజర్ లేదా యజమాని పాత్రలు మాత్రమే కిచెన్ డిస్ప్లేను యాక్సెస్ చేయగలవు.", + "loginSubtitle": "మీ వంటగది సిబ్బంది ఖాతాతో సైన్ ఇన్ చేయండి", + "markAs": "{status} గా గుర్తించు", + "modalOrderNumber": "ఆర్డర్ #{orderNumber}", + "ordersActive": "{count} యాక్టివ్", + "restPolling": "REST పోలింగ్ (ఫాల్బ్యాక్)", + "skipStageMessage": "ఇది ఐటెమ్ను {status} గా గుర్తిస్తుంది మరియు మధ్యలో ఉన్న దశలను దాటవేస్తుంది.", + "skipStageTitle": "దశను దాటవేయాలా?", + "specialInstructionsLabel": "ప్రత్యేక సూచనలు", + "statusDelivered": "డెలివరీ చేయబడింది", + "statusPreparing": "సిద్ధమవుతోంది", + "statusReady": "సిద్ధంగా ఉంది", + "statusVoided": "రద్దు చేయబడింది", + "statusWaiting": "వేచి ఉంది", + "tableLabel": "టేబుల్ {name}", + "title": "కిచెన్ డిస్ప్లే", + "updating": "అప్డేట్ అవుతోంది…", + "viewKanban": "కాన్బాన్", + "viewTabs": "ట్యాబ్లు", + "wsConnected": "WebSocket కనెక్ట్ చేయబడింది" + }, + "nav": { + "collapse": "కుదించు", + "confirmLogout": "మీరు ఖచ్చితంగా లాగ్ అవుట్ చేయాలనుకుంటున్నారా?", + "customers": "కస్టమర్లు", + "dashboard": "డ్యాష్బోర్డ్", + "expenses": "ఖర్చులు", + "heapLabel": "హీప్: ", + "kds": "KDS", + "logout": "లాగ్ అవుట్", + "logoutTooltip": "లాగ్ అవుట్", + "orders": "ఆర్డర్లు", + "portLabel": "పోర్ట్", + "pos": "POS", + "products": "ఉత్పత్తులు", + "serverLabel": "సర్వర్: ", + "serverStatusRunning": "నడుస్తోంది", + "serverStatusStarting": "ప్రారంభమవుతోంది", + "serverStatusStopped": "ఆగిపోయింది", + "serverUnknown": "తెలియదు", + "settings": "సెట్టింగ్లు", + "staff": "సిబ్బంది", + "statusError": "స్థితిని పొందడం విఫలమైంది", + "support": "మద్దతు", + "toggleSidebar": "సైడ్బార్ టోగుల్ చేయి", + "uptimeLabel": "అప్టైమ్: ", + "user": "వినియోగదారు", + "whatsapp": "WhatsApp", + "inventory": "ఇన్వెంటరీ", + "tables": "టేబుళ్లు" + }, + "orders": { + "active": "యాక్టివ్", + "addItem": "ఐటెమ్ జోడించు", + "addItems": "ఆర్డర్కు ఐటెమ్లు జోడించు", + "addItemsCount": "{count} ఐటెమ్(లు) జోడించు", + "addItemsFailed": "ఐటెమ్లు జోడించడం విఫలమైంది", + "adding": "జోడిస్తోంది...", + "all": "అన్నీ", + "allCategories": "అన్ని వర్గాలు", + "allStatuses": "అన్ని స్థితులు", + "allTables": "అన్ని టేబుళ్లు", + "allTypes": "అన్ని రకాలు", + "applyDiscount": "తగ్గింపు వర్తింపజేయి", + "applyDiscountTitle": "తగ్గింపు వర్తింపజేయి - ఆర్డర్ #{number}", + "balance": "బ్యాలెన్స్", + "billNotFound": "బిల్లు కనుగొనబడలేదు", + "cancel": "ఆర్డర్ రద్దు చేయి", + "cancelOrderFailed": "ఆర్డర్ రద్దు చేయడం విఫలమైంది", + "cancelOrderStatusHint": "రద్దు అనేది వంటగది పురోగతిపై ఆధారపడి ఉంటుంది. పెండింగ్ ఆర్డర్లను పిన్ లేకుండా రద్దు చేయవచ్చు. ఆర్డర్ లేదా ఏదైనా ఐటెమ్ సిద్ధమవుతోంది లేదా ఆపై స్థితిలో ఉంటే, యజమాని లేదా మేనేజర్ ఆమోద పిన్ అవసరం. కేవలం కిచెన్ టికెట్ ప్రింట్ చేయడం వల్ల ఈ స్థితి మారదు.", + "cancelReason": "రద్దు చేయడానికి కారణం నమోదు చేయండి", + "cancelled": "రద్దు చేయబడింది", + "cancelling": "రద్దు చేస్తోంది...", + "cartClearConfirm": "మీ యాక్టివ్ POS కార్ట్లో ఐటెమ్లు ఉన్నాయి. కొత్త ఆర్డర్ ప్రారంభించడం వల్ల అవి క్లియర్ అవుతాయి. కొనసాగించాలా?", + "changeCustomer": "కస్టమర్ను మార్చు", + "checkout": "చెకౌట్", + "completed": "పూర్తయింది", + "confirmCancel": "రద్దు నిర్ధారించు", + "confirmPrint": "ప్రింట్ నిర్ధారించు", + "confirmReprint": "రీప్రింట్ నిర్ధారించు", + "confirmVoidItem": "వాయిడ్ నిర్ధారించు", + "convertOrderFailed": "ఆర్డర్ మార్చడం విఫలమైంది", + "convertToTakeaway": "టేక్అవేకి మార్చు", + "convertToTakeawayConfirm": "ఆర్డర్ #{number} ను టేక్అవేకి మార్చాలా{tableNote}?", + "converting": "మారుస్తోంది...", + "customerLinked": "కస్టమర్ లింక్ చేయబడ్డారు", + "customerPhoneMissing": "కస్టమర్ ఫోన్ నంబర్ అందుబాటులో లేదు", + "delete": "తొలగించు", + "deleteHeldConfirm": "మీరు ఖచ్చితంగా ఈ హోల్డ్ చేసిన ఆర్డర్ను తొలగించాలనుకుంటున్నారా?", + "delivery": "డెలివరీ", + "dineIn": "డైన్-ఇన్", + "discountAmountLabel": "తగ్గింపు మొత్తం", + "discountApplied": "తగ్గింపు విజయవంతంగా వర్తింపజేయబడింది", + "discountFailed": "తగ్గింపు వర్తింపజేయడం విఫలమైంది", + "discountPercentageLabel": "తగ్గింపు శాతం", + "discountReason": "తగ్గింపు కోసం కారణం నమోదు చేయండి", + "downloadPrintPreview": "ప్రివ్యూ డౌన్లోడ్ చేయి", + "empty": "ఆర్డర్లు ఏవీ కనుగొనబడలేదు", + "freeTable": "టేబుల్ {name} ఖాళీ చేయి", + "freeTableSuffix": " మరియు టేబుల్ {name} ఖాళీ చేయి", + "generateBillFailed": "బిల్లు రూపొందించడం విఫలమైంది", + "generating": "రూపొందిస్తోంది...", + "guestCount": "{count, plural, one {# అతిథి} other {# మంది అతిథులు}}", + "held": "హోల్డ్ చేసినవి", + "heldEmpty": "హోల్డ్ చేసిన ఆర్డర్లు కనుగొనబడలేదు", + "heldOrderRemoved": "హోల్డ్ చేసిన ఆర్డర్ తీసివేయబడింది", + "historyTitle": "ఆర్డర్ చరిత్ర", + "itemRemoved": "ఐటెమ్ తీసివేయబడింది", + "itemRestored": "ఐటెమ్ పునరుద్ధరించబడింది", + "itemStatusCancelled": "రద్దు చేయబడింది", + "itemStatusPending": "పెండింగ్", + "itemStatusPreparing": "సిద్ధమవుతోంది", + "itemStatusReady": "సిద్ధంగా ఉంది", + "itemStatusServed": "వడ్డించబడింది", + "itemStatusVoidAdjustment": "వాయిడ్ సర్దుబాటు", + "itemStatusVoided": "రద్దు చేయబడింది", + "itemStatusWaiting": "వేచి ఉంది", + "itemVoided": "ఐటెమ్ రద్దు చేయబడింది", + "itemsAdded": "ఆర్డర్కు {count} ఐటెమ్(లు) జోడించబడ్డాయి", + "linkCustomer": "కస్టమర్ను లింక్ చేయి", + "linkCustomerFailed": "కస్టమర్ను లింక్ చేయడం విఫలమైంది", + "linking": "లింక్ చేస్తోంది...", + "loadOrdersFailed": "ఆర్డర్లను లోడ్ చేయడం విఫలమైంది", + "managerPin": "మేనేజర్ పిన్ నమోదు చేయండి", + "managerPinLabel": "మేనేజర్ పిన్", + "managerPinRequired": "తగ్గింపుల కోసం మేనేజర్ పిన్ అవసరం", + "menuLoadFailed": "మెనూ ఐటెమ్లను లోడ్ చేయడం విఫలమైంది", + "moreItems": "+{count} మరిన్ని ఐటెమ్లు", + "newOrder": "కొత్త ఆర్డర్", + "newOrderStarted": "{name} కోసం కొత్త ఆర్డర్ ప్రారంభించబడింది", + "newTotal": "కొత్త మొత్తం", + "noFurtherActions": "ఈ ఆర్డర్ రద్దు చేయబడింది. తదుపరి చర్యలు అందుబాటులో లేవు.", + "noItemsFound": "ఐటెమ్లు ఏవీ కనుగొనబడలేదు", + "notesOptional": "గమనికలు (ఐచ్ఛికం)", + "online": "ఆన్లైన్", + "onlyOwnersRemove": "యజమానులు మరియు మేనేజర్లు మాత్రమే ఐటెమ్లను తీసివేయగలరు", + "orderCancelled": "ఆర్డర్ విజయవంతంగా రద్దు చేయబడింది", + "orderCancelledBanner": "{time} కి రద్దు చేయబడింది · {reason}", + "orderCancelledBannerNoReason": "{time} కి రద్దు చేయబడింది", + "orderConvertedTakeaway": "ఆర్డర్ టేక్అవేకి మార్చబడింది", + "orderNoteTap": "{count, plural, one {1 ఆర్డర్ గమనిక · చూడటానికి ట్యాప్ చేయండి} other {# ఆర్డర్ గమనికలు · చూడటానికి ట్యాప్ చేయండి}}", + "overridePinLabel": "ఓవర్రైడ్ పిన్", + "paid": "చెల్లించబడింది", + "partiallyPaid": "పాక్షికంగా చెల్లించబడింది", + "partiallyRefunded": "పాక్షికంగా రీఫండ్ చేయబడింది", + "refunded": "రీఫండ్ చేయబడింది", + "pending": "పెండింగ్", + "percentOnSubtotal": "(ఉప మొత్తంపై {value}%)", + "preparing": "సిద్ధమవుతోంది", + "printHistory": "ప్రింట్ చరిత్ర", + "printHistoryEntry": "{time} కి {user} ద్వారా {printedType}", + "printPreviewDownloaded": "రసీదు ప్రివ్యూ డౌన్లోడ్ చేయబడింది", + "printPreviewFailed": "రసీదు ప్రివ్యూ రూపొందించడం విఫలమైంది", + "printReceipt": "రసీదు విజయవంతంగా ప్రింట్ చేయబడింది", + "printReceiptConfirm": "మీరు ఖచ్చితంగా ఈ రసీదును ప్రింట్ చేయాలనుకుంటున్నారా?", + "printReceiptFailed": "రసీదు ప్రింట్ చేయడం విఫలమైంది", + "printReceiptReprint": "రసీదు విజయవంతంగా రీప్రింట్ చేయబడింది", + "printReceiptTitle": "రసీదు ప్రింట్ చేయి", + "printed": "ప్రింట్ చేయబడింది", + "printedCount": "{count, plural, one {1 సారి ప్రింట్ చేయబడింది} other {# సార్లు ప్రింట్ చేయబడింది}}", + "transactionNumber": "లావాదేవీ నం.", + "printing": "ప్రింట్ అవుతోంది...", + "ready": "సిద్ధంగా ఉంది", + "receiptPrintFailedHint": "రసీదు ప్రింట్ విఫలమైంది — ప్రింటర్ కనెక్షన్ తనిఖీ చేయండి", + "receiptSent": "రసీదు పంపబడింది", + "refundAmountLabel": "రీఫండ్ మొత్తం", + "refundApprovalPinHint": "ఎంచుకున్న యజమాని లేదా మేనేజర్ యొక్క సిబ్బంది ఆమోద పిన్ ఉపయోగించండి. పరికరం మాస్టర్ పిన్ ఉపయోగించబడదు.", + "refundApprovalPinLabel": "సిబ్బంది ఆమోద పిన్", + "refundApprovalSetupOwner": "రీఫండ్ ఆమోదం కాన్ఫిగర్ చేయబడలేదు. రీఫండ్లు జారీ చేసే ముందు సిబ్బంది విభాగంలో ఆమోద పిన్ సెట్ చేయండి.", + "refundApprovalSetupStaff": "రీఫండ్ ఆమోదం కాన్ఫిగర్ చేయబడలేదు. సిబ్బంది విభాగంలో ఆమోద పిన్ సెట్ చేయమని యజమానిని అడగండి.", + "refundApproverLabel": "ఆమోదించినవారు", + "refundApproverLoadFailed": "రీఫండ్ ఆమోదించేవారిని లోడ్ చేయడం సాధ్యం కాలేదు. మళ్లీ ప్రయత్నించండి.", + "refundApproverPlaceholder": "యజమానిని లేదా మేనేజర్ను ఎంచుకోండి", + "refundBalanceLabel": "రీఫండ్ చేయగల బ్యాలెన్స్: {amount}", + "refundBillLabel": "బిల్లు", + "refundButton": "రీఫండ్", + "refundFailed": "రీఫండ్ ప్రాసెస్ చేయడం సాధ్యం కాలేదు", + "refundIssued": "రీఫండ్ జారీ చేయబడింది", + "refundMethodLabel": "రీఫండ్ విధానం", + "refundMethodStoreCredit": "స్టోర్ క్రెడిట్", + "refundNoEligibleItems": "రీఫండ్కు అర్హమైన ఐటెమ్లు ఏవీ లేవు", + "refundOpenStaff": "సిబ్బంది సెట్టింగ్లు తెరువు", + "refundOwnerPinNotice": "ఈ ఆర్డర్ 1-గంట గడువు దాటింది — ఈ రీఫండ్ను ఆమోదించడానికి యజమాని పిన్ అవసరం.", + "refundPinLabel": "ఆమోద పిన్", + "refundScopeItem": "నిర్దిష్ట ఐటెమ్", + "refundScopeWholeBill": "మొత్తం బిల్లు", + "refundSelectItemPlaceholder": "ఐటెమ్ ఎంచుకోండి", + "refundSubmit": "రీఫండ్ జారీ చేయి", + "removeHeldOrderFailed": "హోల్డ్ చేసిన ఆర్డర్ను తీసివేయడం విఫలమైంది", + "removeItemConfirm": "ఈ ఐటెమ్ తీసివేయాలా?", + "removeItemFailed": "ఐటెమ్ తీసివేయడం విఫలమైంది", + "editItem": "ఐటెమ్ సవరించు", + "editItemTitle": "{name} సవరించు", + "editQuantityTab": "పరిమాణం", + "editReplaceTab": "ఐటెమ్ భర్తీ చేయి", + "editSearchProducts": "ఉత్పత్తులను వెతుకు", + "editNoProducts": "ఉత్పత్తులు ఏవీ కనుగొనబడలేదు", + "editChooseVariant": "వేరియంట్ ఎంచుకోండి", + "editNewQuantity": "కొత్త పరిమాణం", + "itemEdited": "ఐటెమ్ అప్డేట్ చేయబడింది", + "editItemFailed": "ఐటెమ్ను అప్డేట్ చేయడం సాధ్యం కాలేదు", + "removedByManager": "మేనేజర్ తీసివేశారు", + "reopenOrder": "ఆర్డర్ మళ్లీ తెరువు", + "reprint": "రీప్రింట్ చేయబడింది", + "reprintReceiptTitle": "రసీదు రీప్రింట్ చేయి", + "reprintReceiptWarning": "ఈ రసీదు ఇప్పటికే ప్రింట్ చేయబడింది. రీప్రింట్పై \"REPRINT\" బ్యానర్ గుర్తు ఉంటుంది.", + "restoreItemFailed": "ఐటెమ్ పునరుద్ధరించడం విఫలమైంది", + "resumeFailed": "ఆర్డర్ను కొనసాగించడం సాధ్యం కాలేదు", + "resumeInPos": "POS లో కొనసాగించు", + "search": "ఆర్డర్ నంబర్, పేరు లేదా ఫోన్ ద్వారా వెతకండి…", + "searchCustomer": "ఫోన్ లేదా పేరు ద్వారా వెతకండి…", + "searchMenu": "మెనూ ఐటెమ్లను వెతకండి…", + "selectedItems": "ఎంచుకున్న ఐటెమ్లు", + "sendFailed": "పంపడం విఫలమైంది", + "sendReceipt": "రసీదు పంపు", + "printDeliverySlip": "డెలివరీ స్లిప్", + "served": "వడ్డించబడింది", + "settled": "సెటిల్ చేయబడింది", + "startNewOrderForCustomer": "ఈ కస్టమర్ కోసం కొత్త ఆర్డర్ ప్రారంభించు", + "tableAt": "టేబుల్ {name}", + "takePayment": "చెల్లింపు తీసుకోండి", + "takeaway": "టేక్అవే", + "unpaidBadge": "చెల్లించనిది", + "viewActivity": "కార్యకలాపాలు చూడండి", + "viewLogs": "లాగ్లు చూడండి", + "voidItem": "ఐటెమ్ రద్దు చేయి", + "voidItemConfirm": "{name} ఇప్పటికే వంటగదిలో తయారీలో ఉంది. దీన్ని రద్దు చేస్తే బిల్లుకు రీఫండ్ లైన్ జోడించబడుతుంది మరియు దీన్ని వెనక్కి తీసుకోలేరు — మేనేజర్ పిన్ అవసరం.", + "voidItemFailed": "ఐటెమ్ రద్దు చేయడం విఫలమైంది", + "voided": "రద్దు చేయబడింది", + "voidedItemsCount": "{count, plural, one {1 రద్దు చేసిన ఐటెమ్ · చూడటానికి ట్యాప్ చేయండి} other {# రద్దు చేసిన ఐటెమ్లు · చూడటానికి ట్యాప్ చేయండి}}", + "voidingItem": "రద్దు చేస్తోంది...", + "walkInCustomer": "వాక్-ఇన్ కస్టమర్", + "whatsappFailed": "WhatsApp తెరవడం విఫలమైంది", + "selectOrderPlaceholder": "వివరాలు చూడటానికి ఎడమవైపున ఉన్న ఆర్డర్ను ఎంచుకోండి.", + "orderNotInCurrentList": "ఈ ఆర్డర్ ఇకపై ప్రస్తుత జాబితాలో లేదు.", + "orderMissing": "ఈ ఆర్డర్ ఇకపై ఉనికిలో లేదు లేదా అందుబాటులో లేదు.", + "itemCount": "{count, plural, one {1 ఐటెమ్} other {# ఐటెమ్లు}}", + "editPreparationStartedHint": "తయారీ ప్రారంభమైంది. మీరు పరిమాణాన్ని పెంచవచ్చు లేదా తగ్గించవచ్చు. ఉత్పత్తిని మార్చడం అందుబాటులో లేదు.", + "editWasteReasonLabel": "వృథా కారణం (తప్పనిసరి)", + "editWasteReasonPlaceholder": "వంటగది వృథాకు కారణం", + "pendingItemEdit": "పెండింగ్లో ఉన్న ఐటెమ్ సవరణ", + "pendingItemEditHint": "మునుపటి ఫలితం నిర్ధారించబడలేదు. పరిష్కరించడం వల్ల సేవ్ చేసిన సవరణ మళ్లీ ప్రయత్నించబడుతుంది మరియు అది అందకపోతే పూర్తి కావచ్చు.", + "resolvePendingItemEdit": "పెండింగ్ సవరణను పరిష్కరించు", + "resolvingPendingItemEdit": "సవరణను పరిష్కరిస్తోంది...", + "pendingItemEditStorageError": "సేవ్ చేసిన సవరణను చదవడం లేదా అప్డేట్ చేయడం సాధ్యం కాలేదు. ఇది ఈ పరికరంలో ఉంచబడింది.", + "pendingItemEditAuthRequired": "ఈ సవరణను పరిష్కరించడానికి అసలు ఖాతాతో సైన్ ఇన్ చేయండి.", + "pendingItemEditRateLimited": "చాలా అభ్యర్థనలు వచ్చాయి. వేచి ఉండి, ఆపై మళ్లీ పరిష్కరించడానికి ప్రయత్నించండి.", + "pendingItemEditRefreshFailed": "సవరణ నిర్ధారించబడింది, కానీ ప్రస్తుత ఆర్డర్ వివరాలను రిఫ్రెష్ చేయడం సాధ్యం కాలేదు.", + "overridePrice": "ధర మార్చు", + "overridePriceTitle": "ఐటెమ్ ధర మార్చు", + "overridePriceHint": "ఈ లైన్ కోసం అమ్మకపు ధరను సెట్ చేయండి. కాంప్లిమెంటరీ ఐటెమ్ కోసం 0 నమోదు చేయండి.", + "overridePriceNewPrice": "కొత్త యూనిట్ ధర", + "overridePriceReason": "కారణం", + "overridePriceReasonPlaceholder": "ఉదా. కాంప్లిమెంటరీ డెజర్ట్", + "overridePriceSave": "ధర వర్తింపజేయి", + "overridePriceSaved": "ధర అప్డేట్ చేయబడింది", + "overridePriceFailed": "ధరను అప్డేట్ చేయడం సాధ్యం కాలేదు", + "priceOverriddenMenu": "ధర మార్చబడింది (మెనూ {price})", + "overridePriceClear": "మెనూ ధర ఉపయోగించు", + "correctPaymentMethod": "చెల్లింపు విధానాన్ని సరిచేయి", + "correctPaymentMethodHint": "షిఫ్ట్ తెరిచి ఉన్నప్పుడు నమోదు చేసిన చెల్లింపు విధానాన్ని మార్చండి. మొత్తం మారకుండా ఉంటుంది.", + "correctPaymentUnavailable": "అందుబాటులో లేదు: అన్ని విభజించిన బిల్లుల కోసం రీఫండ్లు, వాలెట్ చెల్లింపులు, వ్యాపార రోజు మరియు షిఫ్ట్లను తనిఖీ చేయండి.", + "paymentLineLabel": "చెల్లింపు లైన్", + "paymentMethodCorrected": "చెల్లింపు విధానం అప్డేట్ చేయబడింది", + "correctPaymentMethodFailed": "చెల్లింపు విధానాన్ని అప్డేట్ చేయడం సాధ్యం కాలేదు", + "releaseScheduled": "షెడ్యూల్ చేయబడింది", + "releaseBlocked": "విడుదల నిలిపివేయబడింది" + }, + "pos": { + "addCustomer": "కస్టమర్ జోడించు", + "addItems": "ఐటెమ్లు జోడించు", + "addItemsFailed": "ఐటెమ్లు జోడించడం విఫలమైంది", + "addName": "కొత్త కస్టమర్ జోడించు ({name})", + "addNewItemsAbove": "పైన కొత్త ఐటెమ్లు జోడించండి", + "addPaymentMethod": "మరో చెల్లింపు విధానాన్ని ఉపయోగించండి", + "addToCart": "కార్ట్కు జోడించు - {total}", + "addToOrder": "ఆర్డర్కు {count, plural, one {# ఐటెమ్} other {# ఐటెమ్లు}} జోడించు", + "adding": "జోడిస్తోంది…", + "addingItemsToOrder": "ఆర్డర్ #{number} కు ఐటెమ్లు జోడించబడుతున్నాయి", + "addonPrice": "+{currency}{price}", + "allCategories": "అన్నీ", + "allocateAllItems": "బిల్లులు సృష్టించే ముందు ప్రతి ఐటెమ్ పరిమాణాన్ని కేటాయించండి", + "alreadyOrdered": "ఇప్పటికే ఆర్డర్ చేయబడింది", + "anotherCustomer": "మరో కస్టమర్", + "applyDiscount": "తగ్గింపు వర్తింపజేయి", + "applyingDiscount": "వర్తింపజేస్తోంది…", + "back": "వెనుకకు", + "balanceDue": "చెల్లించాల్సిన బకాయి", + "barcodeNotFound": "బార్కోడ్ {code} కోసం ఉత్పత్తి ఏదీ కనుగొనబడలేదు", + "billNumber": "బిల్లు #{number}", + "calculatingTax": "పన్ను లెక్కిస్తోంది...", + "cart": "కార్ట్", + "cartEmpty": "కార్ట్ ఖాళీగా ఉంది", + "changeReturned": "తిరిగి ఇచ్చిన చిల్లర", + "checkout": "చెకౌట్", + "checkoutInstead": "బదులుగా చెకౌట్ చేయండి", + "close": "మూసివేయి", + "confirmPaymentAmount": "చెల్లింపు నిర్ధారించు · {amount}", + "createChecks": "బిల్లులు సృష్టించు", + "createCustomerFailed": "కస్టమర్ సృష్టించడం విఫలమైంది", + "creating": "సృష్టిస్తోంది…", + "customer": "కస్టమర్", + "customerCreated": "కస్టమర్ సృష్టించబడ్డారు", + "customerFound": "కస్టమర్ కనుగొనబడ్డారు", + "customerFoundClick": "కస్టమర్ కనుగొనబడ్డారు — ఎంచుకోవడానికి పేరుపై క్లిక్ చేయండి", + "customerMismatchTitle": "ఈ టేబుల్పై వేరే కస్టమర్ ఉన్నారు", + "customerMismatchWarning": "ఈ టేబుల్లో ప్రస్తుతం {customer} ఉన్నారు. మీరు కొనసాగి వారి ఆర్డర్కు ఈ ఐటెమ్లను జోడించాలనుకుంటున్నారా?", + "customerName": "పేరు", + "customerAddress": "కస్టమర్ చిరునామా", + "customerRequiredBeforeOrder": "ఆర్డర్ చేసే ముందు కస్టమర్ అవసరం.", + "customerUpdateFailed": "కస్టమర్ అప్డేట్ చేయడం విఫలమైంది", + "customerUpdated": "కస్టమర్ అప్డేట్ చేయబడ్డారు", + "customisable": "అనుకూలీకరించదగినది", + "decreasePax": "అతిథుల సంఖ్య తగ్గించు", + "delivery": "డెలివరీ", + "deliveryAddress": "డెలివరీ చిరునామా", + "expectedPayment": "ఆశించిన చెల్లింపు", + "deliveryNotePlaceholder": "కొరియర్ కోసం డెలివరీ గమనిక", + "discount": "తగ్గింపు", + "discounts": "తగ్గింపులు", + "discountInvalid": "దయచేసి చెల్లబాటు అయ్యే తగ్గింపు విలువను నమోదు చేయండి", + "fixedDiscountMinimum": "స్థిర తగ్గింపులు కనీసం 1 యూనిట్ ఉండాలి", + "discountReasonPlaceholder": "కారణం (ఐచ్ఛికం)", + "discountRemoved": "తగ్గింపు తీసివేయబడింది", + "discountUpdated": "తగ్గింపు అప్డేట్ చేయబడింది", + "editCustomer": "కస్టమర్ సవరించు", + "editItem": "ఐటెమ్ సవరించు", + "enterName": "పేరు నమోదు చేయండి", + "estimatedItemsTotal": "అంచనా వేసిన ఐటెమ్ల మొత్తం", + "failedToUpdateDiscount": "తగ్గింపు అప్డేట్ చేయడం విఫలమైంది", + "flatAmount": "స్థిర మొత్తం", + "free": "ఉచితం", + "freeAddon": "ఉచితం", + "generateBillFailed": "బిల్లు రూపొందించడం విఫలమైంది", + "generating": "రూపొందిస్తోంది…", + "hold": "హోల్డ్", + "holdButton": "హోల్డ్", + "holdOrderFailed": "ఆర్డర్ హోల్డ్ చేయడం విఫలమైంది", + "holdTable": "టేబుల్ హోల్డ్ చేయి", + "increasePax": "అతిథుల సంఖ్య పెంచు", + "invalidPhone": "{country} కోసం ఫోన్ నంబర్ చెల్లదు", + "itemCount": "{count, plural, one {# ఐటెమ్} other {# ఐటెమ్లు}}", + "items": "ఐటెమ్లు", + "itemsAddedToOrder": "ఆర్డర్ #{number} కు ఐటెమ్లు జోడించబడ్డాయి", + "kotPrintFailed": "KOT ప్రింట్ విఫలమైంది", + "loadOrderFailed": "ఆర్డర్ లోడ్ చేయడం విఫలమైంది", + "loadingEllipsis": "…", + "lowStock": "స్టాక్ తక్కువగా ఉంది", + "loyalty": "లాయల్టీ", + "loyaltyPointsShort": "{count} పాయింట్లు", + "loyaltyWallet": "లాయల్టీ వాలెట్", + "managerPin": "మేనేజర్ పిన్", + "managerPinRequired": "తగ్గింపుల కోసం మేనేజర్ పిన్ అవసరం", + "maxSelectionReached": "గరిష్టంగా {count} చేరుకుంది", + "menuLoadFailed": "మెనూ డేటా లోడ్ చేయడం విఫలమైంది", + "methodCard": "కార్డ్", + "methodCash": "నగదు", + "methodWallet": "వాలెట్", + "nameAutoFills": "పేరు ఆటో-ఫిల్ అవుతుంది", + "nameRequired": "పేరు తప్పనిసరి", + "newCustomerEnterName": "కొత్త కస్టమర్ — పేరు నమోదు చేయండి", + "noActiveOrder": "ఈ టేబుల్ కోసం యాక్టివ్ ఆర్డర్ ఏదీ కనుగొనబడలేదు", + "noBalance": "బ్యాలెన్స్ లేదు", + "noPrinters": "ఇంకా ఏ ప్రింటర్లు కాన్ఫిగర్ చేయబడలేదు.", + "noTablesFound": "టేబుళ్లు ఏవీ కనుగొనబడలేదు", + "numberOfChecks": "బిల్లుల సంఖ్య", + "onlinePlatformPlaceholder": "ప్లాట్ఫారమ్ (ఉదా. Swiggy, Zomato)", + "externalOrderIdPlaceholder": "బాహ్య ఆర్డర్ ఐడి", + "orderHeld": "{tableName} కోసం ఆర్డర్ హోల్డ్ చేయబడింది", + "orderHeldFor": "{table} కోసం ఆర్డర్ హోల్డ్ చేయబడింది", + "orderNotesPlaceholder": "ఆర్డర్ గమనికలు (ఐచ్ఛికం)", + "orderNumber": "ఆర్డర్ #{number}", + "orderPaid": "ఆర్డర్ #{number} చెల్లించబడింది!", + "orderPaidWithPoints": "ఆర్డర్ #{number} చెల్లించబడింది! {points} లాయల్టీ పాయింట్లు జమ చేయబడ్డాయి.", + "orderPlaced": "ఆర్డర్ #{number} చేయబడింది!", + "orderStorageUnavailable": "ఈ పరికరం స్థానిక స్టోరేజ్ను బ్లాక్ చేస్తున్నందున ఆర్డర్ సేవ్ కాలేదు. డిస్క్ స్థలాన్ని ఖాళీ చేయండి లేదా FloCafe రీస్టార్ట్ చేసి, మళ్లీ ప్రయత్నించండి.", + "orderStorageNextStep": "ఏ అభ్యర్థన పంపబడలేదు. పరికర స్టోరేజ్ తనిఖీ చేసి, మళ్లీ ప్రయత్నించండి.", + "orderCreatedPaymentNotStarted": "ఆర్డర్ సృష్టించబడింది, కానీ చెల్లింపు ప్రారంభమయ్యే ముందే చెకౌట్ ఆగిపోయింది.", + "openOrdersToPay": "ఈ చెల్లించని ఆర్డర్ను కనుగొని అక్కడ చెకౌట్ కొనసాగించడానికి ఆర్డర్లు తెరవండి.", + "orderTypeDelivery": "డెలివరీ", + "orderTypeDineIn": "డైన్-ఇన్", + "orderTypeOnline": "ఆన్లైన్", + "orderTypeSuffix_delivery": "డెలివరీ ఆర్డర్", + "orderTypeSuffix_dine_in": "డైన్-ఇన్ ఆర్డర్", + "orderTypeSuffix_online": "ఆన్లైన్ ఆర్డర్", + "orderTypeSuffix_takeaway": "టేక్అవే ఆర్డర్", + "orderTypeTakeaway": "టేక్అవే", + "outOfStock": "స్టాక్ లేదు", + "packaging": "ప్యాకేజింగ్", + "paid": "చెల్లించబడింది", + "pax": "అతిథులు", + "pay": "చెల్లించు", + "payment": "చెల్లింపు", + "paymentAboveBalance": "నగదు యేతర మరియు లాయల్టీ వాలెట్ చెల్లింపులు బ్యాలెన్స్ను మించకూడదు", + "paymentBelowBalance": "చెల్లింపు మొత్తం బ్యాలెన్స్ కంటే తక్కువగా ఉంది", + "paymentFailed": "చెల్లింపు విఫలమైంది", + "paymentStatusUnconfirmed": "ప్రస్తుత బిల్లు రిఫ్రెష్ చేయబడింది, కానీ ఈ చెల్లింపు నమోదు చేయబడిందో లేదో ఇది నిర్ధారించదు.", + "paymentRetrySameRequest": "మళ్లీ ప్రయత్నించడం వల్ల అదే అభ్యర్థన కీతో సేవ్ చేసిన అదే చెల్లింపు పంపబడుతుంది. వేరే చెల్లింపును ప్రారంభించవద్దు.", + "checkPaymentStatus": "చెల్లింపు స్థితిని తనిఖీ చేయండి", + "retrySamePayment": "అదే చెల్లింపును పంపండి", + "paymentValidationRejected": "చెల్లింపు నమోదు కాలేదు. చెల్లింపు వివరాలను తనిఖీ చేసి మళ్లీ ప్రయత్నించండి.", + "paymentIncomplete": "చెల్లింపు అసంపూర్ణంగా ఉంది — {amount} ఇంకా బకాయి ఉంది.", + "paymentRecorded": "చెల్లింపు నమోదు చేయబడింది!", + "paymentRecordedWithPoints": "చెల్లింపు నమోదు చేయబడింది! {points} లాయల్టీ పాయింట్లు జమ చేయబడ్డాయి.", + "percentage": "శాతం", + "phone": "ఫోన్", + "placeOrderButton": "ఆర్డర్ చేయి", + "placeOrderFailed": "ఆర్డర్ చేయడం విఫలమైంది", + "placeOrderReady": "సిద్ధంగా ఉన్నప్పుడు ఆర్డర్ చేయండి.", + "placing": "ఆర్డర్ చేస్తోంది...", + "pointsApproxValue": "{count} పాయింట్లు (≈ {value})", + "previousItems": "మునుపటి ఐటెమ్లు (ఇప్పటికే ఆర్డర్ చేసినవి)", + "printHeaderLabel": "ప్రింట్ హెడర్", + "printerAdd": "జోడించు", + "printerAddFirst": "ఇన్స్టాల్ చేసిన ప్రింటర్లను గుర్తిస్తోంది...", + "printerAddManually": "మాన్యువల్గా జోడించు", + "printerBrowserMode": "బ్రౌజర్ ప్రింట్ మోడ్ — సెట్టింగ్లలో మార్చండి", + "printerConnectUsb": "USB ప్రింటర్ కనెక్ట్ చేయి", + "printerConnected": "ప్రింటర్ కనెక్ట్ చేయబడింది", + "printerConnecting": "కనెక్ట్ అవుతోంది…", + "printerDisconnect": "డిస్కనెక్ట్ చేయి", + "printerDisconnected": "ప్రింటర్ డిస్కనెక్ట్ చేయబడింది", + "printerEmptyHint": "పైన ఇన్స్టాల్ చేసిన ప్రింటర్పై జోడించు క్లిక్ చేయండి, లేదా మాన్యువల్గా జోడించు ఉపయోగించండి.", + "printerError": "ప్రింటర్ లోపం", + "printerInstalled": "ఇన్స్టాల్ చేసిన ప్రింటర్లు", + "printerNoPrinter": "ప్రింటర్ లేదు", + "printerReady": "ప్రింటర్ సిద్ధంగా ఉంది", + "printerSectionLabel": "రసీదు ప్రింటర్", + "printerSettings": "సెట్టింగ్లు", + "printerUnknownDevice": "తెలియని పరికరం", + "printingFailed": "ప్రింటింగ్ విఫలమైంది", + "proceedAnyway": "ఏదేమైనా కొనసాగించు", + "processOrderFailed": "ఆర్డర్ ప్రాసెస్ చేయడం విఫలమైంది", + "orderQuantityInvalid": "ఆర్డర్ సృష్టించబడలేదు. ఐటెమ్ పరిమాణాన్ని తనిఖీ చేయండి.", + "orderStockInsufficient": "ఆర్డర్ సృష్టించబడలేదు. అందుబాటులో ఉన్న స్టాక్ చాలా తక్కువగా ఉంది.", + "orderValidationRejected": "ఆర్డర్ సృష్టించబడలేదు. ఆర్డర్ వివరాలను తనిఖీ చేయండి.", + "operationOutcomeUnknown": "ఆర్డర్ లేదా చెల్లింపు సేవ్ చేయబడిందో లేదో FloCafe నిర్ధారించలేకపోయింది.", + "discountOutcomeUnknown": "ఆర్డర్కు తగ్గింపు వర్తింపజేయబడిందో లేదో FloCafe నిర్ధారించలేకపోయింది.", + "billOutcomeUnknown": "ఆర్డర్ ఉంది, కానీ దాని బిల్లు సృష్టించబడిందో లేదో FloCafe నిర్ధారించలేకపోయింది.", + "appendOutcomeUnknown": "ఇప్పటికే ఉన్న ఆర్డర్కు కొత్త ఐటెమ్లు జోడించబడ్డాయో లేదో FloCafe నిర్ధారించలేకపోయింది.", + "appendCompleteCleanupFailed": "ఐటెమ్లు జోడించబడ్డాయి, కానీ ఈ పరికరం స్థానిక రీట్రై స్థితిని క్లియర్ చేయలేకపోయింది.", + "appendCompleteCheckOrders": "ఐటెమ్లను నిర్ధారించడానికి ఆర్డర్లు తెరవండి. ఆర్డర్ తనిఖీ చేసే వరకు వాటిని మళ్లీ జోడించవద్దు.", + "operationMayHaveCompleted": "ఈ చర్య పూర్తయి ఉండవచ్చు. మళ్లీ ప్రయత్నించే ముందు ఆర్డర్ లేదా బిల్లును తనిఖీ చేయండి.", + "operationNotSaved": "ఈ మార్పు సేవ్ చేయబడలేదని FloCafe నిర్ధారించింది.", + "operationNotSavedNextStep": "ప్రస్తుత ఆర్డర్ లేదా బిల్లును తనిఖీ చేసి, ఆపై మళ్లీ ప్రయత్నించండి.", + "operationCorrectAndRetry": "వివరాలను సరిచేసి, ఆపై ఆర్డర్ను మళ్లీ సమర్పించండి.", + "operationCheckBeforeRetry": "మళ్లీ ప్రయత్నించే ముందు ఆర్డర్లు లేదా బిల్లు చెల్లింపు స్థితిని తనిఖీ చేయండి. దాని స్థితి స్పష్టమయ్యే వరకు చర్యను పునరావృతం చేయవద్దు.", + "operationTechnicalDetails": "సాంకేతిక వివరాలు", + "discountInvalidType": "మద్దతు ఉన్న తగ్గింపు రకాన్ని ఎంచుకోండి.", + "discountInvalidValue": "చెల్లబాటు అయ్యే తగ్గింపు మొత్తాన్ని నమోదు చేయండి.", + "discountDisabled": "ఈ స్టోర్ కోసం తగ్గింపులు నిలిపివేయబడ్డాయి.", + "discountTypeDisabled": "ఈ తగ్గింపు రకం నిలిపివేయబడింది.", + "discountLimitExceeded": "తగ్గింపు స్టోర్ పరిమితిని మించిపోయింది.", + "orderNotDiscountable": "ఈ ఆర్డర్కు తగ్గింపు ఇవ్వలేరు.", + "billNotDiscountable": "ఈ బిల్లుకు తగ్గింపు ఇవ్వలేరు.", + "splitCheckDiscountUnavailable": "విభజించిన బిల్లుకు తగ్గింపు ఇవ్వలేరు.", + "refundedDiscountUnavailable": "రీఫండ్ చేసిన బిల్లుకు తగ్గింపు ఇవ్వలేరు.", + "paidDiscountUnavailable": "చెల్లించిన బిల్లుకు తగ్గింపు ఇవ్వలేరు.", + "saleCompletePrintFailed": "అమ్మకం పూర్తయింది, కానీ రసీదు లేదా కిచెన్ టికెట్ ప్రింట్ కాలేదు.", + "saleCompleteReprintNextStep": "ఆర్డర్లు తెరిచి రసీదు లేదా కిచెన్ టికెట్ను మళ్లీ ప్రింట్ చేయండి.", + "saleCompleteCleanupFailed": "అమ్మకం పూర్తయింది, కానీ ఈ పరికరం స్థానిక రీట్రై లేదా హోల్డ్ చేసిన ఆర్డర్ స్థితిని క్లియర్ చేయలేకపోయింది.", + "saleCompleteCheckOrders": "అమ్మకాన్ని నిర్ధారించడానికి ఆర్డర్లు తెరవండి. దాన్ని మళ్లీ సృష్టించవద్దు.", + "processingPayment": "ప్రాసెస్ చేస్తోంది...", + "quantity": "పరిమాణం", + "receiptPrintFailed": "రసీదు ప్రింట్ విఫలమైంది — ప్రింటర్ కనెక్షన్ తనిఖీ చేయండి", + "remainingCount": "{count} మిగిలి ఉన్నాయి", + "remove": "తీసివేయి", + "removeDiscountConfirm": "మీరు ఖచ్చితంగా ఈ తగ్గింపును తీసివేయాలనుకుంటున్నారా?", + "required": "తప్పనిసరి", + "roundOff": "రౌండ్ ఆఫ్", + "saveItemChanges": "మార్పులను సేవ్ చేయి — {total}", + "searchProducts": "ఉత్పత్తులను వెతకండి...", + "select": "ఎంచుకోండి", + "selectAtLeast": "కనీసం {count} ఎంచుకోండి", + "selectCustomer": "కస్టమర్ ఎంచుకోండి", + "selectName": "{name} ఎంచుకోండి", + "selectTable": "టేబుల్ ఎంచుకోండి", + "moreActions": "మరిన్ని చర్యలు", + "selectTableFirst": "మొదట టేబుల్ ఎంచుకోండి", + "selectionComplete": "ఎంపిక పూర్తయింది", + "sendViaWhatsApp": "WhatsApp ద్వారా రసీదు పంపు", + "specialInstructions": "ప్రత్యేక సూచనలు", + "specialInstructionsPlaceholder": "ఉదా., ఉల్లిపాయలు వద్దు, కారం ఎక్కువ...", + "splitCheck": "బిల్లు విభజించు", + "splitPaymentEqually": "చెల్లింపును సమానంగా విభజించు", + "equalSharePayers": "మిగిలిన చెల్లింపుదారులు", + "equalShareNextShare": "తదుపరి వాటా", + "equalShareRoundingNote": "వాటాలు అతి చిన్న కరెన్సీ యూనిట్ తేడాతో ఉంటాయి; మొత్తం మారదు.", + "equalShareApplyTo": "{method} కు వర్తింపజేయి", + "equalShareInvalidCount": "2 నుండి 20 మంది చెల్లింపుదారుల పూర్ణ సంఖ్యను నమోదు చేయండి", + "equalShareTooManyPayers": "అంతమంది చెల్లింపుదారుల మధ్య విభజించడానికి బ్యాలెన్స్ చాలా తక్కువగా ఉంది", + "equalShareConflicts": "వాటాను వర్తింపజేసే ముందు ఇతర మొత్తాలను క్లియర్ చేయండి", + "equalShareInvalidated": "బ్యాలెన్స్ మారింది. సమీక్షించి వాటాను మళ్లీ వర్తింపజేయండి.", + "equalShareLastPayer": "ఒక చెల్లింపుదారు మిగిలి ఉన్నారు; మిగిలిన బ్యాలెన్స్ను సాధారణ చెల్లింపుగా వసూలు చేయండి.", + "equalShareBadge": "సమాన వాటా", + "splitCheckFailed": "బిల్లును విభజించడం సాధ్యం కాలేదు", + "splitCheckHint": "ఐటెమ్లను లేదా పరిమాణాలను వేర్వేరు బిల్లులుగా విభజించండి. చెల్లింపులు ఇప్పటికీ మాన్యువల్గా నమోదు చేయబడతాయి.", + "noSplitCheckItems": "ఈ బిల్లులో విభజించడానికి ఐటెమ్లు ఏవీ మిగిలి లేవు", + "estimateDisclaimer": "బిల్లులు సృష్టించబడినప్పుడు కౌంటర్ తుది మొత్తాలను లెక్కిస్తుంది.", + "estimatedLeavingGuestTotal": "వెళ్తున్న అతిథి అంచనా మొత్తం", + "payThisCheck": "ఈ బిల్లు చెల్లించు", + "allItemsSelected": "అన్నీ ఎంచుకోబడ్డాయి, కాబట్టి విభజించడానికి ఏమీ మిగిలి లేదు", + "remainingCheckLabel": "మిగిలిన అతిథులు", + "leavingGuestLabel": "వెళ్తున్న అతిథి", + "selectAtLeastOneItem": "వెళ్తున్న అతిథి కోసం కనీసం ఒక ఐటెమ్ను ఎంచుకోండి", + "remainingQuantity": "చెల్లించకుండా ఉంటుంది", + "selectedQuantity": "వెళ్తున్న అతిథి", + "sourceQuantity": "ఈ బిల్లులో", + "selectItemsHint": "వెళ్తున్న అతిథి చెల్లిస్తున్న ఐటెమ్లను ఎంచుకోండి. మిగతావన్నీ ఇతర అతిథుల కోసం చెల్లించని బిల్లులో ఉంటాయి.", + "splitModeAll": "అన్ని ఐటెమ్లు", + "splitModeSelected": "ఎంచుకున్న ఐటెమ్లు", + "splitPayment": "విభజిత చెల్లింపు", + "subtotal": "ఉప మొత్తం", + "supportRequestQueueFailed": "మద్దతు అభ్యర్థనను క్యూలో ఉంచడం సాధ్యం కాలేదు", + "tableCleaning": "శుభ్రపరుస్తోంది", + "tableHeld": "హోల్డ్ చేయబడింది", + "tableLabel": "టేబుల్: {name}", + "tableOccupied": "ఆక్రమించబడింది", + "tableReserved": "రిజర్వ్ చేయబడింది", + "tableSeats": "సీట్లు: {count}", + "tagBestseller": "బెస్ట్ సెల్లర్", + "tagContainsNuts": "గింజలు ఉంటాయి", + "tagCount": "{tag} ×{count}", + "tagDairyFree": "పాల రహితం", + "tagEgg": "గుడ్డు", + "tagFragranceFree": "సువాసన రహితం", + "tagGlutenFree": "గ్లూటెన్ రహితం", + "tagLimited": "పరిమితమైనది", + "tagNewArrival": "కొత్తగా వచ్చినది", + "tagNonVeg": "మాంసాహారం", + "tagOrganic": "సేంద్రియ", + "tagSpicy": "కారం", + "tagVeg": "శాకాహారం", + "tagVegan": "వీగన్", + "taxLine": "{title} @{rate}%", + "topItemUnavailable": "అందుబాటులో లేదు", + "topItems": "అగ్ర ఐటెమ్లు", + "topItemsEmpty": "ఇంకా కొనుగోలు చరిత్ర లేదు", + "topItemsLoadFailed": "అగ్ర ఐటెమ్లను లోడ్ చేయడం సాధ్యం కాలేదు", + "total": "మొత్తం", + "totalDue": "చెల్లించాల్సిన మొత్తం", + "unpaid": "చెల్లించనిది", + "updateDiscount": "తగ్గింపు అప్డేట్ చేయి", + "walletMaxAmount": "వాలెట్ మొత్తం అందుబాటులో ఉన్న బ్యాలెన్స్ను మించింది. గరిష్టం: {max}", + "clearAmount": "మొత్తం క్లియర్ చేయి", + "enterFullscreen": "ఫుల్-స్క్రీన్ POS తెరువు", + "exactAmount": "ఖచ్చితమైన బకాయి", + "exitFullscreen": "ఫుల్-స్క్రీన్ POS నుండి నిష్క్రమించు", + "fullscreenUnavailable": "ఫుల్-స్క్రీన్ మోడ్ అందుబాటులో లేదు", + "backspaceAmount": "మొత్తం బ్యాక్స్పేస్", + "numericKeypad": "సంఖ్యా కీప్యాడ్", + "tax": "పన్ను", + "kitchenItemsPendingWarning": "{count, plural, one {# ఐటెమ్ ఇంకా వంటగదిలో సిద్ధమవుతోంది} other {# ఐటెమ్లు ఇంకా వంటగదిలో సిద్ధమవుతున్నాయి}}", + "kitchenDeliveryOverridePrompt": "వంటగది ఐటెమ్లు ఇంకా డెలివరీ కాలేదు. బిల్లింగ్కు అధికారం ఇవ్వడానికి సిబ్బంది ఆమోద పిన్ నమోదు చేయండి.", + "kitchenDeliveryOverrideSuccess": "డెలివరీ కాని ఐటెమ్ల కోసం మేనేజర్ ఓవర్రైడ్ ఆమోదించబడింది.", + "kitchenDeliveryOverrideInvalid": "చెల్లని సిబ్బంది ఆమోద పిన్. దయచేసి మళ్లీ ప్రయత్నించండి.", + "waiveCharge": "మాఫీ చేయి", + "applyCharge": "వర్తింపజేయి", + "addCharge": "జోడించు", + "removeCharge": "తీసివేయి", + "chargesTotal": "మొత్తం ఛార్జీలు", + "chargeUpdateFailed": "ఛార్జీని అప్డేట్ చేయడం సాధ్యం కాలేదు", + "tagHalal": "హలాల్", + "partialPaymentConfirm": "ఇప్పుడు {amount} వసూలు చేయాలా? {remaining} ఇంకా బకాయి ఉంటుంది.", + "paymentTransactionReferenceUsed": "ఈ లావాదేవీ రిఫరెన్స్ ఇప్పటికే మరో బిల్లులో నమోదు చేయబడింది.", + "paymentTransactionReferenceReused": "ఈ లావాదేవీ రిఫరెన్స్ ఇప్పటికే ఈ బిల్లు కోసం నమోదు చేయబడింది.", + "paymentBillRefunded": "ఈ బిల్లు రీఫండ్ చేయబడింది. కొత్త చెల్లింపు జోడించలేరు.", + "paymentBillAlreadyPaid": "ఈ బిల్లు ఇప్పటికే చెల్లించబడింది.", + "paymentCustomerMismatch": "ఎంచుకున్న కస్టమర్ ఈ బిల్లులోని కస్టమర్తో సరిపోలడం లేదు.", + "paymentCustomerUnavailable": "ఈ బిల్లుకు లింక్ చేసిన కస్టమర్ కనుగొనబడలేదు.", + "paymentWalletCustomerRequired": "లాయల్టీ వాలెట్ ఉపయోగించే ముందు ఈ బిల్లుకు కస్టమర్ను లింక్ చేయండి.", + "paymentAmountRequired": "ప్రతి విభజిత చెల్లింపు కోసం మొత్తాన్ని నమోదు చేయండి.", + "paymentCashReferenceZeroApplied": "ఈ నగదు లైన్ బిల్లుకు ఏమీ జోడించదు. విభజిత మొత్తాలను సర్దుబాటు చేయండి లేదా దాని లావాదేవీ రిఫరెన్స్ను తీసివేయండి.", + "paymentWalletInsufficient": "ఈ చెల్లింపు కోసం లాయల్టీ వాలెట్లో తగినంత బ్యాలెన్స్ లేదు.", + "paymentIdempotencyConflict": "ఈ చెల్లింపు అభ్యర్థన ఇప్పటికే మరో చెల్లింపుకు లింక్ చేయబడింది. మళ్లీ ప్రయత్నించే ముందు బిల్లును తనిఖీ చేయండి.", + "paymentMethodUnavailable": "ఈ చెల్లింపు విధానం ఇకపై అందుబాటులో లేదు. మరో విధానాన్ని ఎంచుకోండి.", + "paymentInputInvalid": "చెల్లింపు వివరాలు చెల్లవు. విధానం, మొత్తం మరియు లావాదేవీ రిఫరెన్స్ తనిఖీ చేయండి.", + "cardTransactionIdLabel": "టెర్మినల్ లావాదేవీ నంబర్", + "cardTransactionIdMissing": "కార్డ్ టెర్మినల్ నుండి లావాదేవీ నంబర్ నమోదు చేయండి.", + "paymentCompletionApplied": "చెల్లింపు నమోదు చేయబడింది, కానీ FloCafe తదుపరి అప్డేట్ను పూర్తి చేయలేకపోయింది. మరో చెల్లింపు తీసుకునే ముందు బిల్లును తనిఖీ చేయండి.", + "paymentCorrectAndRetry": "చెల్లింపు వివరాలను సరిచేయండి లేదా మరో విధానాన్ని ఎంచుకుని, ఆపై మళ్లీ ప్రయత్నించండి.", + "chargeRequired": "అప్డేట్ చేసే ముందు ఛార్జీని ఎంచుకోండి.", + "chargeBillNotFound": "బిల్లు కనుగొనబడలేదు.", + "chargeSplitCheck": "విభజించిన బిల్లుపై ఛార్జీలను మార్చలేరు.", + "chargeBillPaid": "చెల్లించిన బిల్లుపై ఛార్జీలను మార్చలేరు.", + "chargeBillRefunded": "రీఫండ్ చేసిన బిల్లుపై ఛార్జీలను మార్చలేరు.", + "chargeOrderNotFound": "ఈ బిల్లుకు లింక్ చేసిన ఆర్డర్ కనుగొనబడలేదు.", + "chargeOrderCancelled": "రద్దు చేసిన ఆర్డర్పై ఛార్జీలను మార్చలేరు.", + "chargeUnavailable": "ఈ ఛార్జీ అందుబాటులో లేదు.", + "chargeOrderTypeUnsupported": "ఈ ఆర్డర్ రకానికి ఈ ఛార్జీ వర్తించదు.", + "chargeChangeRequired": "ఈ ఛార్జీని జోడించాలో లేదా మాఫీ చేయాలో ఎంచుకోండి.", + "chargeInvalidChangeType": "ఈ ఛార్జీ అప్డేట్ చెల్లదు.", + "chargeNotWaivable": "ఈ ఛార్జీని మాఫీ చేయలేరు.", + "chargeAlwaysApplied": "ఈ ఛార్జీ ఎల్లప్పుడూ వర్తిస్తుంది మరియు తీసివేయలేరు.", + "chargeCompletionApplied": "ఛార్జీ అప్డేట్ చేయబడింది, కానీ FloCafe తదుపరి దశను పూర్తి చేయలేకపోయింది. మళ్లీ మార్చే ముందు ప్రస్తుత బిల్లును సమీక్షించండి.", + "cashMovementShortcut": "నగదు లావాదేవీలను తెరువు", + "clearCartShortcut": "యాక్టివ్ కార్ట్ క్లియర్ చేయి (నిర్ధారణతో)", + "decrementQuantityShortcut": "చివరి ఐటెమ్ పరిమాణాన్ని తగ్గించు", + "dismissModalOrBlurShortcut": "యాక్టివ్ ఇన్పుట్ నుండి బయటకు రా లేదా యాక్టివ్ మోడల్ మూసివేయి", + "fullscreenShortcut": "POS ఫుల్-స్క్రీన్ టోగుల్ చేయి", + "incrementQuantityShortcut": "చివరి ఐటెమ్ పరిమాణాన్ని పెంచు", + "keyboardShortcutsSubtitle": "వేగవంతమైన క్యాషియర్ ఆపరేషన్ కోసం హై-స్పీడ్ POS హాట్కీలు", + "keyboardShortcutsTitle": "కీబోర్డ్ షార్ట్కట్లు", + "multiplierSearchShortcut": "ఉత్పత్తి శోధనలో పరిమాణ ప్రిఫిక్స్ (ఉదా. 3*latte)", + "shortcutCategoryCart": "కార్ట్ & సర్దుబాట్లు", + "shortcutCategoryCashier": "వేగవంతమైన క్యాషియర్ & చెల్లింపు", + "shortcutCategoryNavigation": "నావిగేషన్ & నియంత్రణలు", + "shortcutCategorySearch": "శోధన & జాబితా", + "showKeyboardShortcutsShortcut": "కీబోర్డ్ షార్ట్కట్ల గైడ్ చూపించు", + "spaceTenderShortcut": "చెకౌట్ వద్ద ఆర్డర్ చేయి లేదా నగదు చెల్లించు", + "swapNameAndPhone": "పేరు & ఫోన్ మార్చు", + "createWithPhone": "ఫోన్తో కస్టమర్ సృష్టించు: {phone}", + "createWithName": "పేరుతో కస్టమర్ సృష్టించు: {name}", + "splitItemsIntoChecks": "ఐటెమ్లను బిల్లులుగా విభజించు", + "splitCheckAvailabilityFailed": "బిల్లు విభజన లభ్యతను తనిఖీ చేయడం సాధ్యం కాలేదు.", + "splitCheckPermissionRequired": "బిల్లులను విభజించడానికి మీకు అనుమతి లేదు.", + "splitCheckResolvePaymentFirst": "విభజించే ముందు ప్రస్తుత చెల్లింపును పూర్తి చేయండి లేదా పరిష్కరించండి.", + "splitCheckBeforePaymentOnly": "ఏదైనా చెల్లింపు నమోదు చేసే ముందే బిల్లులను విభజించండి.", + "splitCheckDineInOnly": "డైన్-ఇన్ బిల్లులను మాత్రమే విభజించవచ్చు.", + "splitCheckWholeUnitsOnly": "విభజనకు పూర్ణ ఐటెమ్ పరిమాణాలు అవసరం.", + "splitCheckTwoUnitsRequired": "కనీసం రెండు అర్హమైన ఐటెమ్ యూనిట్లు అవసరం.", + "splitCheckCheckAvailability": "లభ్యతను తనిఖీ చేయి", + "viewMore": "మరిన్ని చూడండి", + "viewLess": "తక్కువ చూడండి", + "splitCheckSettingDenied": "ఈ ఖాతా బిల్లు విభజన లభ్యతను తనిఖీ చేయలేదు.", + "dayCloseBlockedByOpenShiftTitle": "ఓపెన్ షిఫ్ట్ను మొదట ముగించాలి", + "dayCloseBlockedByOpenShiftHint": "ఈ వ్యాపార రోజును ముగించే ముందు ఓపెన్ షిఫ్ట్ #{id} ({name}) ను ముగించండి.", + "shiftCloseUnpaidWarningTitle": "{count, plural, one {# ఓపెన్ ఆర్డర్ తదుపరి షిఫ్ట్కు బదిలీ అవుతుంది} other {# ఓపెన్ ఆర్డర్లు తదుపరి షిఫ్ట్కు బదిలీ అవుతాయి}}", + "shiftCloseUnpaidWarningHint": "ఈ ఆర్డర్లు తదుపరి షిఫ్ట్ కోసం తెరిచే ఉంటాయి. ఈ షిఫ్ట్ను ముగించడం వల్ల ఈ షిఫ్ట్లో ఇప్పటికే వసూలు చేసిన నగదు చెల్లింపులు మాత్రమే సరిపోల్చబడతాయి.", + "shiftCloseUnpaidMoreCount": "+{count} మరిన్ని ఓపెన్ ఆర్డర్లు", + "lockTerminal": "టెర్మినల్ లాక్ చేయి", + "selectOpenShift": "ముగించాల్సిన షిఫ్ట్", + "xReportShiftFilterLabel": "షిఫ్ట్ పరిధి", + "xReportAllShifts": "అన్ని షిఫ్ట్లు (పూర్తి రోజు)", + "sendToKitchenAt": "వంటగదికి పంపే సమయం", + "sendToKitchenHint": "స్టోర్ సమయం ({timezone}) - ఈ సమయానికి వంటగదికి విడుదల అవుతుంది", + "scheduleOrderToggle": "తర్వాత కోసం షెడ్యూల్ చేయి", + "sendImmediately": "వెంటనే పంపు", + "scheduledOrders": "షెడ్యూల్ చేసినవి", + "scheduledOrdersTitle": "షెడ్యూల్ చేసిన ఆర్డర్లు", + "scheduledOrdersEmpty": "వంటగది విడుదలకు వేచి ఉన్న షెడ్యూల్ చేసిన ఆర్డర్లు లేవు.", + "scheduledSectionBlocked": "శ్రద్ధ అవసరం", + "scheduledSectionUpcoming": "రాబోయేవి", + "scheduledPaidBlockedBadge": "చెల్లించబడింది - విడుదల నిలిపివేయబడింది", + "scheduledReleaseBlockedBadge": "విడుదల నిలిపివేయబడింది", + "scheduledReleaseNow": "ఇప్పుడే విడుదల చేయి", + "scheduledRetryRelease": "విడుదల మళ్లీ ప్రయత్నించు", + "scheduledReschedule": "రీషెడ్యూల్ చేయి", + "scheduledSaveTime": "సమయం సేవ్ చేయి", + "scheduledPay": "చెల్లించు", + "scheduledAddItems": "ఐటెమ్లు జోడించు", + "scheduledEditLockedPaid": "చెల్లింపు తర్వాత ఐటెమ్ మరియు ఆర్థిక సవరణలు లాక్ చేయబడతాయి. రీఫండ్ లేదా చెల్లింపు సవరణను ఉపయోగించండి.", + "scheduledRefundBeforeCancel": "ఈ షెడ్యూల్ చేసిన ఆర్డర్ను రద్దు చేసే ముందు వసూలు చేసిన చెల్లింపును రీఫండ్ చేయండి.", + "scheduledReleasedSuccess": "ఆర్డర్ #{number} వంటగదికి విడుదల చేయబడింది", + "scheduledUpdatedSuccess": "#{number} కోసం వంటగది విడుదల సమయం అప్డేట్ చేయబడింది", + "scheduledOrderPlaced": "ఆర్డర్ #{number} {time} కి షెడ్యూల్ చేయబడింది", + "scheduledAddingToBanner": "షెడ్యూల్ చేసిన ఆర్డర్ #{number} ({time}) కు ఐటెమ్లు జోడించబడుతున్నాయి", + "scheduledPastTimeError": "షెడ్యూల్ చేసిన వంటగది విడుదల సమయం భవిష్యత్తులో ({timezone}) ఉండాలి.", + "scheduledDstSkippedError": "{timezone} లో డేలైట్-సేవింగ్ మార్పు వల్ల ఆ స్థానిక సమయం దాటవేయబడింది. గడియారం మార్పు తర్వాత చెల్లబాటు అయ్యే సమయాన్ని ఎంచుకోండి.", + "scheduledDstAmbiguousError": "{timezone} లో డేలైట్-సేవింగ్ మార్పు సమయంలో ఆ స్థానిక సమయం రెండుసార్లు వస్తుంది. పునరావృతమయ్యే గంట వెలుపల స్పష్టమైన సమయాన్ని ఎంచుకోండి.", + "scheduledInvalidTimeError": "స్టోర్ టైమ్జోన్ ({timezone}) లో చెల్లబాటు అయ్యే తేదీ మరియు సమయాన్ని నమోదు చేయండి.", + "ticketLoaded": "టికెట్ #{number} లోడ్ చేయబడింది", + "ticketNotFound": "టికెట్ కనుగొనబడలేదు లేదా ఇప్పటికే చెల్లించబడింది", + "sendToPaymentDeliveryError": "డెలివరీ ఆర్డర్లకు మల్టీ-కౌంటర్ ఆర్డరింగ్ అందుబాటులో లేదు.", + "orderSentToPaymentSuccess": "ఆర్డర్ #{number} చెల్లింపుకు పంపబడింది", + "sendToPayment": "చెల్లింపుకు పంపు", + "paymentTicketPrinted": "చెల్లింపు టికెట్ ప్రింట్ చేయబడింది", + "paymentTicketPrintFailed": "చెల్లింపు టికెట్ ప్రింట్ చేయడం విఫలమైంది", + "partialPaid": "చెల్లించినది: {paid}", + "releaseBlockedTitle": "విడుదల నిలిపివేయబడింది", + "printTicket": "టికెట్ ప్రింట్ చేయి", + "payTicket": "చెల్లించు", + "paymentQueue": "చెల్లింపు క్యూ", + "paymentQueueRefreshPaused": "పాత టికెట్లను చూస్తున్నప్పుడు ఆటోమేటిక్ రిఫ్రెష్ తాత్కాలికంగా నిలిపివేయబడుతుంది.", + "scanOrEnterTicket": "టికెట్ QR స్కాన్ చేయండి లేదా నంబర్ నమోదు చేయండి...", + "paymentQueueEmpty": "వేచి ఉన్న టికెట్లు లేవు", + "paymentQueueEmptyDesc": "చెల్లింపుకు పంపిన ఆర్డర్లు ఇక్కడ కనిపిస్తాయి.", + "paidBlockedSection": "చెల్లించబడింది — విడుదల నిలిపివేయబడింది", + "awaitingPaymentSection": "చెల్లింపు కోసం వేచి ఉంది", + "paymentTicket": "చెల్లింపు టికెట్", + "paymentTicketDesc": "టికెట్ సృష్టించబడి చెల్లింపు క్యూకు పంపబడింది.", + "ticketNumber": "టికెట్ నంబర్", + "paymentTicketInstruction": "చెల్లించడానికి ఈ టికెట్ను చెల్లింపు కౌంటర్కు తీసుకెళ్లండి.", + "selectCounter": "కౌంటర్ ఎంచుకోండి" + }, + "printTest": { + "amt": "మొత్తం", + "browserDialogOpened": "బ్రౌజర్ ప్రింట్ డైలాగ్ తెరవబడింది!", + "browserHint": "బ్రౌజర్ ప్రింట్ డైలాగ్ ఉపయోగిస్తుంది - కంప్యూటర్కు కనెక్ట్ చేయబడిన ఏ ప్రింటర్తోనైనా పనిచేస్తుంది", + "browserPrint": "బ్రౌజర్ ప్రింట్", + "copyText": "టెక్స్ట్ కాపీ చేయి", + "dataPreview": "టెస్ట్ డేటా ప్రివ్యూ", + "downloadBin": ".bin డౌన్లోడ్ చేయి", + "downloadHtml": "HTML డౌన్లోడ్ చేయి", + "escpos": "ESCPOS (USB)", + "escposHint": "స్థితి: {status} - WebUSB ద్వారా నేరుగా USB ప్రింటింగ్", + "failedWithReason": "ప్రింట్ విఫలమైంది: {message}", + "htmlDownloaded": "HTML డౌన్లోడ్ చేయబడింది", + "item": "ఐటెమ్", + "kotDisabled": "KOT నిలిపివేయబడింది", + "kitchenStation": "వంటగది", + "kotPrinted": "KOT ప్రింట్ చేయబడింది!", + "lastPrintedBytes": "చివరిగా ప్రింట్ చేసినవి: {bytes} బైట్లు", + "optionBasicReceipt": "ప్రాథమిక రసీదు (థర్మల్)", + "optionKot": "KOT (కిచెన్ టికెట్)", + "optionTaxBill": "వివరమైన పన్ను బిల్లు (థర్మల్)", + "optionWhatsapp": "WhatsApp షేర్", + "optionWebPrint": "వెబ్ ప్రింట్ (బ్రౌజర్)", + "kotLanguageLoadError": "KOT భాష \"{language}\" లోడ్ చేయడం సాధ్యం కాలేదు, కాబట్టి ఇంగ్లీష్ లేబుళ్లు ఉపయోగించబడ్డాయి. లోకేల్ బండిల్ తనిఖీ చేసి మళ్లీ ప్రయత్నించండి.", + "paperWidth58": "2.5\" (58mm)", + "paperWidth80": "3.5\" (80mm)", + "paperWidthLabel": "పేపర్ వెడల్పు", + "printMethodLabel": "ప్రింట్ విధానం", + "printerSettings": "ప్రింటర్ సెట్టింగ్లు", + "printing": "ప్రింట్ అవుతోంది...", + "qty": "పరిమాణం", + "rate": "ధర", + "receiptPrinted": "రసీదు ప్రింట్ చేయబడింది!", + "runTest": "టెస్ట్ రన్ చేయి", + "selectTestType": "టెస్ట్ రకాన్ని ఎంచుకోండి", + "taxBillPrinted": "వివరమైన పన్ను బిల్లు ప్రింట్ చేయబడింది!", + "title": "ప్రింటింగ్ టెస్ట్ పేజీ", + "webPrintDialogOpened": "ప్రింట్ డైలాగ్ తెరవబడింది", + "whatsappCopied": "WhatsApp సందేశం క్లిప్బోర్డ్కు కాపీ చేయబడింది", + "whatsappOpened": "WhatsApp తెరవబడింది" + }, + "printWarnings": { + "title": "{count, plural, one {# లైన్ ప్రింట్ కాలేదు} other {# లైన్లు ప్రింట్ కాలేదు}}", + "arabicShapingHint": "మీ ప్రింటర్ పర్షియన్/అరబిక్ టెక్స్ట్ను ప్రింట్ చేయలేకపోయింది. సెట్టింగ్లు → ప్రింటింగ్లో \"ప్రింటర్ అరబిక్/పర్షియన్ షేపింగ్కు మద్దతు ఇస్తుంది\" ఆన్ చేయండి, లేదా బ్రౌజర్ ద్వారా ప్రింట్ చేయండి.", + "genericHint": "దిగువ లైన్లలో ఈ థర్మల్ ప్రింటర్ రెండర్ చేయలేని అక్షరాలు ఉన్నాయి.", + "moreLines": "…మరియు మరో {count}", + "languageLoadError": "ప్రింట్ భాషా బండిల్(లు) \"{languages}\" లోడ్ చేయడం సాధ్యం కాలేదు. లోకేల్ బండిల్ను తనిఖీ చేసి, మళ్లీ ప్రయత్నించడానికి యాప్ను రీలోడ్ చేయండి.", + "printerOfflineHint": "ప్రింటర్ స్పందించడం లేదు. అది ఆన్లో ఉందని మరియు కనెక్ట్ చేయబడిందని నిర్ధారించుకోండి, ఆపై Windowsలో ప్రింటర్ క్యూ తెరిచి \"Use Printer Offline\" ఆఫ్ చేయండి.", + "templateFallback": "ఎంచుకున్న బిల్లు టెంప్లేట్కు ఈ ప్రింట్ మార్గంలో మద్దతు లేదు, కాబట్టి అంతర్నిర్మిత రసీదు లేఅవుట్ ఉపయోగించబడింది." + }, + "print": { + "menu": { + "title": "మెనూ", + "totalItems": "మొత్తం ఐటెమ్లు" + }, + "taxInvoiceTitle": "పన్ను ఇన్వాయిస్", + "invoiceTitle": "ఇన్వాయిస్", + "invoiceNumber": "ఇన్వాయిస్ #:", + "time": "సమయం", + "customerShort": "కస్టమర్", + "numberShort": "కస్టమర్ నం", + "customerDetails": "కస్టమర్ వివరాలు", + "address": "చిరునామా", + "call": "కాల్", + "note": "గమనిక", + "phoneLong": "ఫోన్", + "subtotalExclTax": "ఉప మొత్తం (పన్ను మినహా)", + "serviceChargeShort": "సర్వీస్ ఛార్జ్", + "grandTotal": "మొత్తం", + "thankYouShort": "ధన్యవాదాలు!", + "thankYouVisitAgain": "మీ సందర్శనకు ధన్యవాదాలు!", + "pleaseComeAgain": "దయచేసి మళ్లీ రండి!", + "ratesInclusiveNote": "ధరలలో పన్నులు కలిసి ఉంటాయి", + "pointsEarned": "సంపాదించిన పాయింట్లు", + "pointsBalance": "పాయింట్ల బ్యాలెన్స్", + "pointsRedeemed": "రిడీమ్ చేసిన పాయింట్లు", + "kot": { + "title": "కిచెన్ ఆర్డర్ టికెట్", + "banner": "కిచెన్ ఆర్డర్ టికెట్", + "station": "స్టేషన్", + "type": "రకం", + "noPendingItems": "పెండింగ్ ఐటెమ్లు లేవు", + "end": "ముగింపు" + }, + "deliverySlip": { + "title": "డెలివరీ స్లిప్", + "banner": "డెలివరీ స్లిప్", + "address": "డెలివరీ చిరునామా", + "addressTruncated": "... మరో {count} అక్షరాలు చూపబడలేదు, ఆర్డర్ను తనిఖీ చేయండి", + "paid": "చెల్లించబడింది", + "toCollect": "వసూలు చేయాల్సింది", + "refunded": "రీఫండ్ చేయబడింది", + "partiallyRefunded": "పాక్షికంగా రీఫండ్ చేయబడింది", + "cashOnDelivery": "క్యాష్ ఆన్ డెలివరీ", + "amountDue": "చెల్లించాల్సిన మొత్తం", + "multiplePaymentMethods": "బహుళ చెల్లింపు విధానాలు", + "expectedPayment": "ఆశించిన చెల్లింపు", + "deliveryNote": "డెలివరీ గమనిక" + }, + "hsn": "HSN", + "zReport": { + "title": "Z నివేదిక", + "businessDate": "తేదీ:", + "periodStart": "వ్యవధి ప్రారంభం:", + "periodEnd": "వ్యవధి ముగింపు:", + "openingFloat": "ప్రారంభ నగదు", + "cashMovements": "నగదు లావాదేవీలు", + "payIn": "నగదు జమ", + "payOut": "నగదు ఉపసంహరణ", + "safeDrop": "సేఫ్ డ్రాప్", + "payments": "చెల్లింపు విధానం వారీగా అమ్మకాలు", + "refunds": "రీఫండ్లు", + "tax": "పన్ను వివరాలు", + "staff": "సిబ్బంది అమ్మకాలు", + "expectedCash": "ఆశించిన నగదు", + "countedCash": "లెక్కించిన నగదు", + "variance": "తేడా", + "closedBy": "మూసివేసినవారు:", + "operatorSignature": "ఆపరేటర్ సంతకం:", + "footer": "FloCafe ద్వారా రూపొందించబడింది", + "none": "(ఏదీ లేదు)", + "paymentCount": "x{count}", + "count": "సంఖ్య:", + "amount": "మొత్తం:" + }, + "test": { + "title": "Flo ప్రింటర్ టెస్ట్", + "networkUsb": "నెట్వర్క్ / USB టెస్ట్ ప్రింట్", + "columns": "నిలువు వరుసలు", + "wrapHint": "తదుపరి లైన్ చుట్టుకుంటే, తక్కువ నిలువు వరుసల విలువను ఎంచుకోండి.", + "success": "మీరు దీన్ని చదవగలిగితే, మీ ప్రింటర్ పనిచేస్తోంది!" + } + }, + "products": { + "includeDescriptions": "వివరణలను చేర్చు", + "includeModifiers": "మాడిఫైయర్లను చేర్చు", + "addAddon": "యాడ్-ఆన్ జోడించు", + "addAddonGroup": "యాడ్-ఆన్ గ్రూప్ జోడించు", + "addAddonGroupForm": "యాడ్-ఆన్ గ్రూప్ జోడించు", + "addAddonGroupTitle": "యాడ్-ఆన్ గ్రూప్ జోడించు", + "addAddonInline": "+ యాడ్-ఆన్ జోడించు", + "addButton": "జోడించు", + "addCategory": "వర్గం జోడించు", + "addCategoryTitle": "వర్గం జోడించు", + "addProduct": "ఉత్పత్తి జోడించు", + "addProductTitle": "ఉత్పత్తి జోడించు", + "addonAddons": "యాడ్-ఆన్లు", + "addonAllowMultipleQuantities": "ప్రతి యాడ్-ఆన్కు బహుళ పరిమాణాలను అనుమతించు", + "addonEmpty": "ఇంకా యాడ్-ఆన్ గ్రూపులు లేవు.", + "addonGroupCount": "{count, plural, one {# గ్రూప్} other {# గ్రూపులు}}", + "addonGroupCreated": "యాడ్-ఆన్ గ్రూప్ సృష్టించబడింది", + "addonGroupDeleted": "యాడ్-ఆన్ గ్రూప్ తొలగించబడింది", + "addonGroupUpdated": "యాడ్-ఆన్ గ్రూప్ అప్డేట్ చేయబడింది", + "addonMax": "గరిష్ట ఎంపిక", + "addonMin": "కనీస ఎంపిక", + "addonNamePlaceholder": "యాడ్-ఆన్ పేరు", + "addonPricePlaceholder": "ధర", + "addonRequired": "తప్పనిసరి", + "addonSelectionRange": "{min} – {max}", + "assignTaxCategory": "పన్ను వర్గాన్ని కేటాయించు", + "barcodeLabel": "బార్కోడ్: {barcode}", + "cashbackGlobalBadge": "గ్లోబల్", + "cashbackLabel": "లాయల్టీ క్యాష్బ్యాక్", + "cashbackOverrideHint": "ఇది ఈ ఉత్పత్తికి మాత్రమే గ్లోబల్ రేటును ఓవర్రైడ్ చేస్తుంది. గ్లోబల్ రేటును మళ్లీ ఉపయోగించడానికి ఫీల్డ్ను క్లియర్ చేయండి.", + "cashbackUsingGlobal": "సెట్టింగ్ల నుండి గ్లోబల్ రేటు ({rate}%) ఉపయోగించబడుతోంది. ఈ ఉత్పత్తి కోసం దాన్ని ఓవర్రైడ్ చేయడానికి విలువను నమోదు చేయండి, లేదా మినహాయించడానికి 0 నమోదు చేయండి.", + "categoryAndProductsDeleted": "వర్గం మరియు అన్ని ఉత్పత్తులు తొలగించబడ్డాయి", + "categoryAssignPartial": "{total} ఉత్పత్తులలో {assigned} కు వర్గం కేటాయించబడింది — {failed} విఫలమయ్యాయి", + "categoryAssignSuccess": "{count} ఉత్పత్తి(ల)కు పన్ను వర్గం కేటాయించబడింది", + "categoryColor": "రంగు", + "categoryCreated": "వర్గం సృష్టించబడింది", + "categoryDeleted": "వర్గం తొలగించబడింది", + "categoryDescription": "వివరణ", + "categoryEmpty": "ఇంకా వర్గాలు లేవు. మీ మొదటి వర్గాన్ని జోడించండి!", + "categoryInactiveBadge": "వర్గం ఇనాక్టివ్", + "categoryName": "పేరు", + "categoryUpdated": "వర్గం అప్డేట్ చేయబడింది", + "colorAmber": "అంబర్", + "colorBlue": "నీలం", + "colorCyan": "సియాన్", + "colorEmerald": "పచ్చ", + "colorFuchsia": "ఫుషియా", + "colorGreen": "ఆకుపచ్చ", + "colorIndigo": "ఇండిగో", + "colorLabel": "రంగు", + "colorLime": "నిమ్మ ఆకుపచ్చ", + "colorNone": "ఏదీ లేదు", + "colorOrange": "నారింజ", + "colorPink": "గులాబీ", + "colorPurple": "ఊదా", + "colorRed": "ఎరుపు", + "colorRose": "రోజ్", + "colorSky": "ఆకాశ నీలం", + "colorTeal": "టీల్", + "colorViolet": "వయొలెట్", + "colorYellow": "పసుపు", + "columnActions": "చర్యలు", + "columnAddons": "యాడ్-ఆన్లు", + "columnCashback": "క్యాష్బ్యాక్", + "columnCategory": "వర్గం", + "columnPrice": "ధర", + "columnProduct": "ఉత్పత్తి", + "columnRequired": "తప్పనిసరి", + "columnSelection": "ఎంపిక", + "columnStatus": "స్థితి", + "columnStock": "స్టాక్", + "columnTax": "పన్ను", + "costLabel": "ఖర్చు: {value}", + "create": "సృష్టించు", + "createProduct": "ఉత్పత్తి సృష్టించు", + "created": "ఉత్పత్తి సృష్టించబడింది", + "cropImage": "చిత్రాన్ని క్రాప్ చేయి", + "csvAddonsCreated": "సృష్టించిన యాడ్-ఆన్లు:", + "csvAddonsHelp": "నిలువు వరుసలు: group_name, addon_name, price, group_required (yes/no), group_min_select, group_max_select — ఆ గ్రూప్ పేరుతో ఉన్న మొదటి వరుస నుండి గ్రూప్ సెట్టింగ్లు చదవబడతాయి", + "csvBlankTemplate": "ఖాళీ టెంప్లేట్", + "csvCategoriesHelp": "నిలువు వరుసలు: name, description, color (red/green/blue/...), icon (emoji), sort_order", + "csvChooseFile": "CSV ఫైల్ ఎంచుకోవడానికి క్లిక్ చేయండి", + "csvCurrentData": "ప్రస్తుత డేటా", + "csvGroupsCreated": "సృష్టించిన గ్రూపులు:", + "csvImporting": "దిగుమతి చేస్తోంది…", + "csvMissingFields": "కొన్ని వరుసలలో ఫీల్డ్లు లేవు — డిఫాల్ట్ విలువలతో దిగుమతి చేయబడ్డాయి", + "csvModalTitle": "CSV దిగుమతి / ఎగుమతి — {type}", + "csvProductsHelp": "నిలువు వరుసలు: id (కొత్త ఐటెమ్ల కోసం ఖాళీగా ఉంచండి), sku, name, category, price, description, cost, tax_category, tax_behavior, cashback_percent, tags (veg/non_veg/...), is_active (yes/no). పన్ను లేకపోతే tax_category ఖాళీగా ఉంచండి — ఐటెమ్ ఐడిలు పొందడానికి \"ప్రస్తుత డేటా\" డౌన్లోడ్ చేసి, సవరించి, ఉన్న ఐటెమ్లను అప్డేట్ చేయడానికి మళ్లీ అప్లోడ్ చేయండి", + "csvSkippedErrors": "లోపాల కారణంగా దాటవేయబడిన వరుసలు", + "defaultCategoryTag": "{name} (డిఫాల్ట్)", + "deleteAddonGroupConfirm": "ఈ యాడ్-ఆన్ గ్రూప్ను తొలగించాలా?", + "deleteCategoryAndProducts": "వర్గం & అన్ని ఉత్పత్తులను తొలగించు", + "deleteCategoryBody": "\"{name}\" లో {count, plural, one {# యాక్టివ్ ఉత్పత్తి ఉంది} other {# యాక్టివ్ ఉత్పత్తులు ఉన్నాయి}}. వాటితో మీరు ఏమి చేయాలనుకుంటున్నారు?", + "deleteCategoryTitle": "వర్గాన్ని తొలగించు", + "deleteConfirm": "ఈ ఉత్పత్తిని తొలగించాలా?", + "deleted": "ఉత్పత్తి తొలగించబడింది", + "download": "డౌన్లోడ్", + "editAddonGroupTitle": "యాడ్-ఆన్ గ్రూప్ సవరించు", + "editCategoryTitle": "వర్గం సవరించు", + "editProductTitle": "ఉత్పత్తి సవరించు", + "empty": "ఇంకా ఉత్పత్తులు లేవు. మీ మొదటి ఉత్పత్తిని జోడించండి!", + "failedToLoad": "ఉత్పత్తులను లోడ్ చేయడం విఫలమైంది", + "failedToSave": "ఉత్పత్తిని సేవ్ చేయడం విఫలమైంది", + "failedToSaveAddonGroup": "యాడ్-ఆన్ గ్రూప్ సేవ్ చేయడం విఫలమైంది", + "failedToSaveCategory": "వర్గాన్ని సేవ్ చేయడం విఫలమైంది", + "fieldActive": "యాక్టివ్", + "fieldAddonGroups": "యాడ్-ఆన్ గ్రూపులు", + "inheritedFromCategory": "వర్గం నుండి వారసత్వంగా వచ్చింది", + "fieldBarcode": "బార్కోడ్", + "fieldBarcodeHint": "నేరుగా కార్ట్కు జోడించడానికి POS వద్ద ఈ ఉత్పత్తిని స్కాన్ చేయండి.", + "fieldBarcodePlaceholder": "బార్కోడ్ స్కాన్ చేయండి లేదా టైప్ చేయండి", + "fieldAllowFractionalQuantity": "భిన్న పరిమాణం", + "fieldCategory": "వర్గం", + "fieldCostPrice": "కొనుగోలు ధర", + "fieldImage": "ఉత్పత్తి చిత్రం", + "fieldInventoryProduct": "ఇన్వెంటరీ ఉత్పత్తి", + "fieldInventoryProductHint": "ఈ ఉత్పత్తిని అమ్మడం వల్ల ఎంచుకున్న స్టాక్ ఉత్పత్తి నుండి దిగువ పరిమాణం తగ్గించబడుతుంది.", + "fieldInventoryProductNone": "ఏదీ లేదు", + "fieldInventoryDeductionQuantity": "ప్రతి అమ్మకానికి తగ్గింపు", + "fieldLowStockThreshold": "తక్కువ స్టాక్ పరిమితి", + "fieldName": "పేరు", + "fieldSaleUnit": "అమ్మకపు యూనిట్", + "fieldSku": "SKU", + "fieldStock": "ప్రస్తుత స్టాక్", + "fieldTags": "ట్యాగ్లు", + "fieldTaxType": "పన్ను రకం", + "fieldTrackInventory": "ఇన్వెంటరీ ట్రాక్ చేయి", + "fieldWeightPrecision": "ఖచ్చితత్వం", + "hiddenOnPos": "(POS లో దాచబడింది)", + "imageCamera": "కెమెరా", + "imageCompressFailed": "ఈ చిత్రాన్ని తగినంతగా కంప్రెస్ చేయడం సాధ్యం కాలేదు. మరింత దగ్గరగా క్రాప్ చేయండి లేదా మరో చిత్రాన్ని ప్రయత్నించండి.", + "imageCropApply": "వర్తింపజేయి", + "imageCropFailed": "చిత్రాన్ని క్రాప్ చేయడం విఫలమైంది", + "imageDropActive": "చిత్రాన్ని ఇక్కడ వదలండి...", + "imageDropIdle": "చిత్రాన్ని ఇక్కడ లాగి వదలండి, లేదా బ్రౌజ్ చేయడానికి క్లిక్ చేయండి", + "imageFetch": "తీసుకో", + "imageFetchFailed": "URL నుండి చిత్రాన్ని పొందడం సాధ్యం కాలేదు", + "imageFetching": "తీసుకుంటోంది...", + "imageHttpsOnly": "HTTPS URLలకు మాత్రమే మద్దతు ఉంది", + "imageMaxSize": "గరిష్టం {size} MB. చిత్రాలు WebPకి కంప్రెస్ చేయబడతాయి.", + "imageOrUse": "లేదా ఉపయోగించండి", + "imagePasteUrl": "URL పేస్ట్ చేయి", + "imageReadFailed": "చిత్ర ఫైల్ చదవడం విఫలమైంది", + "imageReady": "చిత్రం సిద్ధంగా ఉంది", + "imageSelectFile": "దయచేసి చిత్ర ఫైల్ను ఎంచుకోండి", + "imageTooLarge": "ఫైల్ చాలా పెద్దదిగా ఉంది (గరిష్టం {size} MB)", + "imageUrlHint": "HTTPS URLలకు మాత్రమే మద్దతు ఉంది. చిత్రం తీసుకోబడి, క్రాప్ చేయబడి, స్థానికంగా నిల్వ చేయబడుతుంది.", + "importComplete": "దిగుమతి పూర్తయింది", + "invalidCashbackRate": "దయచేసి చెల్లబాటు అయ్యే లాయల్టీ క్యాష్బ్యాక్ రేటును నమోదు చేయండి (0–100%)", + "maxSelection": "గరిష్ట ఎంపిక", + "minSelection": "కనీస ఎంపిక", + "moveAndDelete": "తరలించు & వర్గాన్ని తొలగించు", + "moveProductsTo": "ఉత్పత్తులను ఇక్కడికి తరలించు", + "nameLabel": "పేరు", + "notTaxedBadge": "పన్ను లేదు", + "notTaxedTooltip": "ఏ పన్ను వర్గం కేటాయించబడలేదు — ఈ ఉత్పత్తికి పన్ను విధించబడదు మరియు పన్ను లైన్ ప్రింట్ చేయబడదు.", + "optional": "ఐచ్ఛికం", + "optionalTag": "ఐచ్ఛికం", + "priceLabel": "ధర ({currency})", + "saleUnitCl": "సె.లీ", + "saleUnitEach": "ఒక్కొక్కటి", + "saleUnitFlOz": "ఫ్లూ.ఔన్స్", + "saleUnitG": "గ్రా", + "saleUnitKg": "కి.గ్రా", + "saleUnitL": "లీ", + "saleUnitLb": "పౌండ్", + "saleUnitMl": "మి.లీ", + "saleUnitOz": "ఔన్స్", + "reassignAndDelete": "ఉత్పత్తులు తిరిగి కేటాయించబడ్డాయి మరియు వర్గం తొలగించబడింది", + "required": "తప్పనిసరి", + "requiredSelection": "తప్పనిసరి ఎంపిక", + "requiredTag": "తప్పనిసరి", + "selectCategoryPlaceholder": "వర్గాన్ని ఎంచుకోండి…", + "selectPlaceholder": "ఎంచుకోండి", + "skuLabel": "SKU: {sku}", + "tabAddonGroups": "యాడ్-ఆన్ గ్రూపులు", + "tabCategories": "వర్గాలు", + "tabProducts": "ఉత్పత్తులు", + "tagBestseller": "బెస్ట్ సెల్లర్", + "tagContainsNuts": "గింజలు ఉంటాయి", + "tagDairyFree": "పాల రహితం", + "tagEgg": "గుడ్డు", + "tagFragranceFree": "సువాసన రహితం", + "tagGlutenFree": "గ్లూటెన్ రహితం", + "tagLimited": "పరిమితమైనది", + "tagNewArrival": "కొత్తగా వచ్చినది", + "tagNonVeg": "మాంసాహారం", + "tagOrganic": "సేంద్రియ", + "tagPlaceholder": "ట్యాగ్ టైప్ చేసి Enter నొక్కండి", + "tagSpicy": "కారం", + "tagVeg": "శాకాహారం", + "tagVegan": "వీగన్", + "taxAllAssigned": "ప్రతి యాక్టివ్ ఉత్పత్తికి ఇప్పటికే పన్ను వర్గం కేటాయించబడింది.", + "taxApplyToProducts": "{count} ఉత్పత్తి(ల)కు వర్తింపజేయి", + "taxBehaviorLabel": "పన్ను విధానం", + "taxBulkBody": "ఇంకా పాత మాన్యువల్ రేటులో ఉన్న అన్ని {count} యాక్టివ్ ఉత్పత్తి(ల)కు ఒకే పన్ను వర్గాన్ని వర్తింపజేయండి. ఇప్పటికే స్వంత వర్గం సెట్ చేయబడిన ఉత్పత్తులు మార్చబడవు.", + "taxCountryDefault": "దేశ డిఫాల్ట్", + "taxDefaultHint": "స్టోర్ డిఫాల్ట్ స్వయంచాలకంగా ఎంచుకోబడుతుంది. ఉత్పత్తి చట్టపరంగా వేరే రేటును ఉపయోగించినప్పుడు లేదా మినహాయించబడినప్పుడు మాత్రమే దీన్ని మార్చండి.", + "taxExclusive": "పన్ను అదనం", + "taxExclusiveShort": "అదనం", + "taxExempt": "మినహాయింపు", + "taxInclusive": "పన్ను కలిపి", + "taxInclusiveShort": "కలిపి", + "taxNoCategory": "పన్ను వర్గం ఎంచుకునే వరకు పన్ను లెక్కించబడదు లేదా ప్రింట్ చేయబడదు.", + "taxNoGroupsHint": "సెట్టింగ్లలో దేశ పన్నులు ఆన్ చేసే వరకు పన్ను గ్రూపులు అందుబాటులో ఉండవు.", + "taxNoTax": "— పన్ను లేదు / మినహాయింపు —", + "taxNone": "పన్ను లేదు", + "taxRateGroupLabel": "పన్ను రేటు గ్రూప్", + "taxRateHint": "ఈ వర్గం కోసం యాక్టివ్ పన్ను ప్రొఫైల్ నుండి రేటు నిర్ణయించబడుతుంది, మాన్యువల్గా నమోదు చేయబడదు.", + "taxRateLabel": "పన్ను రేటు (%)", + "title": "ఉత్పత్తులు", + "update": "అప్డేట్", + "updateProduct": "ఉత్పత్తి అప్డేట్ చేయి", + "updated": "ఉత్పత్తి అప్డేట్ చేయబడింది", + "uploadCsv": "CSV అప్లోడ్ చేయి", + "printMenu": "మెనూ ప్రింట్ చేయి", + "printMenuDescription": "ప్రింట్ చేసే మెనూ రోల్లో చేర్చాల్సిన ఐటెమ్లను కాన్ఫిగర్ చేయండి.", + "printDestination": "ప్రింట్ గమ్యస్థానం", + "printToReceipt": "రసీదు ప్రింటర్", + "printToPaper": "పేపర్ (A4 / లెటర్)", + "printToPdf": "PDF గా సేవ్ చేయి", + "includeInactiveItems": "ఇనాక్టివ్ ఐటెమ్లను చేర్చు", + "includeOutOfStockItems": "స్టాక్ లేని ఐటెమ్లను చేర్చు", + "includeHiddenItems": "దాచిన ఐటెమ్లను చేర్చు", + "menuPrintedSuccess": "మెనూ విజయవంతంగా ప్రింట్ చేయబడింది", + "noProductsToPrint": "ఎంచుకున్న ప్రమాణాలకు సరిపోయే ఉత్పత్తులు లేవు", + "printerDestination": "ప్రింటర్", + "systemBrowserPrint": "సిస్టమ్ / బ్రౌజర్ ప్రింట్", + "menuPrintFailed": "మెనూను ప్రింట్ చేయడం సాధ్యం కాలేదు", + "menuPopupBlocked": "మీ బ్రౌజర్ ప్రింట్ విండోను బ్లాక్ చేసింది. ఈ సైట్ కోసం పాప్-అప్లను అనుమతించి మళ్లీ ప్రయత్నించండి.", + "dietaryTagsLabel": "ఆహార ట్యాగ్లు", + "variantGovernedHint": "ధర మరియు స్టాక్ దిగువ వేరియంట్ల ద్వారా నియంత్రించబడతాయి.", + "variantMoveDown": "క్రిందికి జరుపు", + "variantMoveUp": "పైకి జరుపు", + "variantOnlinePrice": "ఆన్లైన్ ధర", + "variantRecipeMultiplier": "రెసిపీ గుణకం", + "variantRecipeMultiplierHint": "ఈ వేరియంట్ వినియోగించే రెసిపీ భాగాలు: 1 అంటే ఒక బేస్ రెసిపీ భాగం, 0.5 సగం, 2 రెట్టింపు. లింక్ చేసిన ఉత్పత్తి స్టాక్ నుండి వేరుగా ఉంటుంది.", + "variantRowInvalid": "ప్రతి వేరియంట్కు పేరు, ధర మరియు సున్నా కంటే ఎక్కువ రెసిపీ గుణకం ఉండాలి.", + "variantToggle": "ఈ ఉత్పత్తికి వేరియంట్లు ఉన్నాయి (ఉదా. పరిమాణం, క్రస్ట్, ఫ్లేవర్)", + "variantsSection": "వేరియంట్లు", + "variantDeactivateConfirm": "సేవ్ చేసినప్పుడు ఈ వేరియంట్ డీయాక్టివేట్ చేయబడుతుంది మరియు ఈ స్క్రీన్ నుండి పునరుద్ధరించబడదు.", + "variantRemoveAllConfirm": "దీన్ని ఆఫ్ చేయడం వల్ల ఈ ఉత్పత్తి యొక్క ప్రతి వేరియంట్ డీయాక్టివేట్ అవుతుంది. గత ఆర్డర్లలో అవి అలాగే ఉంటాయి.", + "parentCategory": "పేరెంట్ వర్గం", + "parentCategoryNone": "ఏదీ లేదు (టాప్-లెవల్)" + }, + "productAnalytics": { + "title": "తదుపరి ఏమి నిర్మించాలో నిర్ణయించడంలో మాకు సహాయపడండి", + "intro": "FloCafe ఒక చిన్న బృందంచే నిర్మించబడింది. మీరు ఏ స్క్రీన్లను ఉపయోగిస్తున్నారో మరియు ఎక్కడ లోపాలు జరుగుతున్నాయో తెలుసుకోవడం ద్వారా మొదట ఏమి సరిచేయాలో మరియు మా కృషిని ఎక్కడ పెట్టాలో మాకు తెలుస్తుంది.", + "alreadyOn": "ఇప్పటికే ఆన్లో ఉంది", + "usageTitle": "అజ్ఞాత వినియోగం", + "usageBody": "మీరు ఏ ఫీచర్లను ఉపయోగిస్తారు, రోజువారీ ఆర్డర్ల సంఖ్య, మీ దేశం మరియు యాప్ వెర్షన్, యాదృచ్ఛిక ఇన్స్టాల్ ఐడితో. మీ ఈమెయిల్ ఎప్పుడూ ఉండదు.", + "errorsTitle": "లోప నివేదికలు", + "errorsBody": "ఏదైనా సమస్య వచ్చినప్పుడు మేము ఆ లోపాన్ని చూసి సరిచేస్తాము, తరచుగా మీరు నివేదించే ముందే. కస్టమర్ లేదా అమ్మకాల డేటా ఉండదు.", + "stepFurther": "మరో అడుగు ముందుకు వేయాలనుకుంటున్నారా?", + "linkBody": "ఈ డేటాను మీ ఖాతా ఈమెయిల్ ({email}) కు లింక్ చేయండి, తద్వారా మీరు సపోర్ట్ను సంప్రదించినప్పుడు మీ సెటప్ను మేము చూడగలము మరియు మీరు ఎదుర్కొన్న సమస్య పరిష్కారమైనప్పుడు మీకు తెలియజేయగలము. మేము దీన్ని ఎప్పుడూ విక్రయించము లేదా ప్రకటనల కోసం ఉపయోగించము.", + "fullHint": "మీ ఖాతా ఈమెయిల్కు లింక్ చేయబడిన వినియోగ మరియు లోప డేటా, తద్వారా సపోర్ట్ మీ సెటప్ను చూడగలదు మరియు మీరు ఎదుర్కొన్న సమస్య పరిష్కారమైనప్పుడు మేము మీకు తెలియజేయగలము.", + "anonymousHint": "యాదృచ్ఛిక ఇన్స్టాల్ ఐడితో వినియోగ మరియు లోప డేటా. మీ ఈమెయిల్ ఎప్పుడూ ఉండదు.", + "neverSee": "కస్టమర్ పేర్లు, ఫోన్ నంబర్లు, ఆర్డర్ వివరాలు, అమ్మకాల మొత్తాలు, చెల్లింపులు లేదా సిబ్బంది పాస్వర్డ్లను మేము ఎప్పుడూ చూడము.", + "linkEmail": "నా ఈమెయిల్ లింక్ చేయి", + "keepAnonymous": "అజ్ఞాతంగా ఉంచు", + "dontShare": "వినియోగ డేటాను షేర్ చేయవద్దు", + "changeLater": "మీరు దీన్ని ఎప్పుడైనా సెట్టింగ్లు → గోప్యతలో మార్చవచ్చు, అక్కడ మీరు వినియోగ డేటాను ఆఫ్ కూడా చేయవచ్చు.", + "choiceRequired": "కొనసాగించడానికి వినియోగ డేటాను ఎలా షేర్ చేయాలో ఎంచుకోండి.", + "settingsLabel": "వినియోగ డేటా", + "settingsHint": "ఏ ఫీచర్లను మొదట మెరుగుపరచాలో వినియోగ డేటా మాకు చెబుతుంది. ఇందులో కస్టమర్ పేర్లు, ఆర్డర్ వివరాలు, అమ్మకాల మొత్తాలు లేదా చెల్లింపులు ఎప్పుడూ ఉండవు.", + "levelFull": "నా ఖాతా ఈమెయిల్కు లింక్ చేయబడింది", + "levelAnonymous": "అజ్ఞాతం: యాదృచ్ఛిక ఇన్స్టాల్ ఐడి, నా ఈమెయిల్ ఎప్పుడూ ఉండదు", + "levelOff": "ఆఫ్", + "saveFailed": "సేవ్ చేయడం సాధ్యం కాలేదు. మళ్లీ ప్రయత్నించండి." + }, + "receipt": { + "amount": "మొత్తం", + "billNumber": "బిల్లు #", + "cashReceived": "స్వీకరించిన నగదు", + "customerNo": "కస్టమర్ నం", + "date": "తేదీ", + "deliveryCharge": "డెలివరీ ఛార్జ్", + "economicCode": "ఎకనామిక్ కోడ్", + "grandTotal": "గ్రాండ్ టోటల్", + "item": "ఐటెమ్", + "onlineOrder": "ఆన్లైన్ ఆర్డర్", + "payments": "చెల్లింపులు", + "phone": "ఫోన్", + "printBill": "బిల్లు ప్రింట్ చేయి", + "qty": "పరిమాణం", + "rate": "ధర", + "reprint": "రీప్రింట్", + "serviceCharge": "సర్వీస్ ఛార్జ్", + "table": "టేబుల్", + "taxDetails": "పన్ను వివరాలు", + "taxIncluded": "వర్తించే చోట పన్ను కలిపి ఉంటుంది", + "thankYou": "మీ సందర్శనకు ధన్యవాదాలు!", + "totalTax": "మొత్తం పన్ను" + }, + "restore": { + "failedWith": "పునరుద్ధరణ విఫలమైంది: {error}", + "success": "డేటాబేస్ విజయవంతంగా పునరుద్ధరించబడింది. రీస్టార్ట్ అవుతోంది..." + }, + "serverApp": { + "addToOrder": "ఆర్డర్కు జోడించు", + "billPrintFailed": "ఆర్డర్ పంపబడింది, కానీ బిల్లు ప్రింట్ కాలేదు", + "couldNotLoadData": "సర్వర్ యాప్ డేటాను లోడ్ చేయడం సాధ్యం కాలేదు", + "couldNotSendOrder": "ఆర్డర్ పంపడం సాధ్యం కాలేదు", + "currentTicket": "ప్రస్తుత టికెట్", + "customerNamePlaceholder": "కస్టమర్ పేరు", + "disabledHint": "సెట్టింగ్ల నుండి టేబుల్సైడ్ ఆర్డరింగ్ను మళ్లీ ఆన్ చేయమని యజమానిని లేదా మేనేజర్ను అడగండి.", + "disabledTitle": "సర్వర్ యాప్ నిలిపివేయబడింది", + "draftTotal": "డ్రాఫ్ట్ మొత్తం", + "draftDiscardedOnUserChange": "మునుపటి సిబ్బంది డ్రాఫ్ట్ విస్మరించబడింది.", + "emailPlaceholder": "server@flo.local", + "emptyDraft": "వాటిని ఇక్కడ జోడించడానికి మెనూ ఐటెమ్లపై ట్యాప్ చేయండి.", + "guestFallbackName": "అతిథి {last4}", + "itemNotePlaceholder": "ఐటెమ్ గమనిక", + "kitchen": "వంటగది", + "kotPrintFailed": "ఆర్డర్ పంపబడింది, కానీ కిచెన్ టికెట్ ప్రింట్ కాలేదు", + "loginHint": "సర్వర్, మేనేజర్ మరియు యజమాని ఖాతాల కోసం టేబుల్సైడ్ ఆర్డరింగ్", + "loginSubtitle": "సర్వీస్ సిబ్బంది కోసం టేబుల్సైడ్ ఆర్డరింగ్", + "newItems": "కొత్త ఐటెమ్లు", + "noTablesHint": "టేబుల్సైడ్ ఆర్డరింగ్ డైన్-ఇన్ సేవ కోసం. టేబుళ్లు జోడించమని లేదా సెట్టింగ్లలో టేబుల్సైడ్ ఆర్డరింగ్ ఆఫ్ చేయమని యజమానిని లేదా మేనేజర్ను అడగండి.", + "noTablesTitle": "టేబుళ్లు ఏవీ సెటప్ చేయబడలేదు", + "openOrder": "ఓపెన్ ఆర్డర్", + "orderSent": "ఆర్డర్ పంపబడింది", + "orderSlipDeliveryCharge": "డెలివరీ ఛార్జ్", + "orderSlipDiscount": "తగ్గింపు", + "orderSlipPackagingCharge": "ప్యాకేజింగ్ ఛార్జ్", + "orderSlipServiceCharge": "సర్వీస్ ఛార్జ్", + "orderSlipSubtotal": "ఉప మొత్తం", + "orderSlipTax": "పన్ను", + "orderSlipTitle": "ఆర్డర్ స్లిప్", + "orderSlipTotal": "మొత్తం", + "phonePlaceholder": "ఫోన్", + "refreshFailed": "రిఫ్రెష్ విఫలమైంది", + "searchMenu": "మెనూ వెతుకు", + "selectTable": "టేబుల్ ఎంచుకోండి", + "sendToKitchen": "వంటగదికి పంపు", + "sending": "పంపుతోంది...", + "signInFailed": "సైన్ ఇన్ విఫలమైంది", + "statusPreparing": "సిద్ధమవుతోంది", + "statusReady": "సిద్ధంగా ఉంది", + "statusServed": "వడ్డించబడింది", + "statusWaiting": "వేచి ఉంది", + "tableLabel": "టేబుల్ {name}", + "tables": "టేబుళ్లు", + "title": "సర్వర్ యాప్" + }, + "settings": { + "aboutDescription": "FloPOS అనేది కేఫ్లు, రెస్టారెంట్లు, బేకరీలు, ఫుడ్ ట్రక్కులు, క్లౌడ్ కిచెన్లు మరియు బార్ల కోసం ఎప్పటికీ ఉచిత, ఓపెన్-సోర్స్ రెస్టారెంట్ POS. ఇందులో ఆర్డరింగ్, టేబుళ్లు, మెనూలు, కిచెన్ డిస్ప్లే, రసీదు ప్రింటింగ్, సిబ్బంది యాక్సెస్ మరియు లోకల్ డేటా స్టోరేజ్ ఉంటాయి. దీన్ని డౌన్లోడ్ చేసుకోండి, సర్వీస్ నడపండి, మీ డేటాను మీ దగ్గరే ఉంచుకోండి మరియు మీ POS పై పూర్తి నియంత్రణ కలిగి ఉండండి.", + "aboutFloCafe": "FloCafe గురించి", + "aboutGithub": "GitHub రిపాజిటరీ", + "aboutWebsite": "యాప్ వెబ్సైట్", + "account": "ఖాతా", + "accountAndApp": "ఖాతా & యాప్", + "actionFailed": "విఫలమైంది", + "actions": "చర్యలు", + "active": "యాక్టివ్", + "addFirstCounter": "మల్టీ-కౌంటర్ ఆర్డరింగ్ ప్రారంభించడానికి మీ మొదటి కౌంటర్ను జోడించండి.", + "addPrinter": "ప్రింటర్ జోడించండి", + "addPrinterManually": "మాన్యువల్గా జోడించండి", + "addStation": "స్టేషన్ జోడించండి", + "address": "చిరునామా", + "addressPlaceholder": "వీధి, నగరం", + "adminOnly": "అడ్మిన్ మాత్రమే", + "allSaveFailed": "సెట్టింగ్లను సేవ్ చేయడం విఫలమైంది", + "allSaved": "సెట్టింగ్లు సేవ్ చేయబడ్డాయి", + "apiKey": "API కీ", + "apiKeyHelp": "దీన్ని soflo.codify.tech నుండి పొందండి → మీ స్టోర్ను నమోదు చేయండి → API కీని కాపీ చేయండి", + "apiKeyHint": "(మాన్యువల్ — పైన నమోదు చేసి ఉంటే ఐచ్ఛికం)", + "apiKeyInputPlaceholder": "fac_live_xxxxxxxxxxxxxxxxxxxx", + "apiKeyRequired": "ముందుగా API కీని నమోదు చేయండి", + "appQrAlt": "{name} QR కోడ్", + "appleDevices": "Apple పరికరాలు (mDNS)", + "appleDevicesHint": "mDNS మద్దతు ఉన్న iOS, macOS మరియు కొన్ని Android పరికరాల్లో పనిచేస్తుంది. మీ రౌటర్లో Bonjour/mDNS ప్రారంభించబడి ఉండాలి.", + "applyGlobalRateAction": "ఈ {count} ఉత్పత్తులకు గ్లోబల్ రేటును ఉపయోగించండి", + "applyGlobalRateDone": "{count} ఉత్పత్తులు ఇప్పుడు గ్లోబల్ రేటును ఉపయోగిస్తున్నాయి", + "applyGlobalRateHint": "{count} ఉత్పత్తులు లాయల్టీ సంపాదించకుండా సెట్ చేయబడ్డాయి, కాబట్టి వాటికి గ్లోబల్ రేటు వర్తించదు. అది ఉద్దేశపూర్వకంగా కాకపోతే వాటిని గ్లోబల్ రేటుకు మార్చండి. కస్టమ్ రేటు ఉన్న ఉత్పత్తులు ప్రభావితం కావు.", + "applyGlobalRateTitle": "ప్రస్తుతం ఏమీ సంపాదించని ఉత్పత్తులు", + "applyGlobalRateWorking": "అప్డేట్ అవుతోంది…", + "applySafeFixes": "{count, plural, one {# సురక్షిత పరిష్కారాన్ని} other {# సురక్షిత పరిష్కారాలను}} వర్తింపజేయండి", + "applyingFixes": "వర్తింపజేస్తోంది…", + "applyingFixesFailed": "పరిష్కారాలను వర్తింపజేయడం విఫలమైంది", + "autoPrintBill": "బిల్ ఆటో-ప్రింట్", + "autoPrintBillHint": "చెల్లింపు పూర్తయినప్పుడు బిల్ ప్రింట్ చేయండి", + "autoPrintKot": "KOT ఆటో-ప్రింట్", + "autoPrintKotDisabledHint": "పైన KOT ప్రింటింగ్ ఆఫ్ చేయబడింది, కాబట్టి దీని ప్రభావం ఉండదు.", + "autoPrintKotHint": "ఆర్డర్ వేసినప్పుడు KOT ప్రింట్ చేయండి", + "backupCreated": "బ్యాకప్ విజయవంతంగా సృష్టించబడింది", + "backupDeleteFailed": "బ్యాకప్ను తొలగించడం విఫలమైంది", + "backupDeleted": "బ్యాకప్ తొలగించబడింది", + "backupFailed": "బ్యాకప్ విఫలమైంది", + "backupFailedGeneric": "బ్యాకప్ విఫలమైంది", + "backupHistory": "బ్యాకప్ చరిత్ర", + "backupHistoryEmpty": "ఇంకా బ్యాకప్లు లేవు", + "backupHistoryHint": "డిఫాల్ట్ లొకేషన్లో సేవ్ చేయబడిన బ్యాకప్లు. క్రింద వాటిలో దేనినైనా పునరుద్ధరించండి.", + "counterIsActiveHint": "పరికర ఎంపిక కోసం అందుబాటులో ఉంది.", + "counterLoadFailed": "కౌంటర్లను లోడ్ చేయడం విఫలమైంది.", + "counterNameRequired": "కౌంటర్ పేరు అవసరం.", + "counterRoleCombinedHint": "ఈ కౌంటర్లో ఆర్డర్లు సృష్టించండి మరియు చెల్లింపులు స్వీకరించండి.", + "counterRoleOrderingHint": "ఇక్కడ ఆర్డర్లు సిద్ధం చేసి చెల్లింపు కౌంటర్కు పంపండి.", + "counterRolePaymentHint": "ఇక్కడ షేర్డ్ క్యూను తెరిచి చెల్లింపు స్వీకరించండి.", + "localBackupTitle": "ఆటోమేటిక్ రోజువారీ బ్యాకప్", + "localBackupHint": "Flo Cafe ప్రారంభమైనప్పుడు మరియు మూసివేయబడినప్పుడు బ్యాకప్ కోసం తనిఖీ చేస్తుంది (గత గంటలో తీసుకుని ఉంటే దాటవేయబడుతుంది), మరియు రోజుకు కనీసం ఒక కాపీని {folder} లో సేవ్ చేసి సరికొత్త {count} కాపీలను ఉంచుతుంది. మీరు Flo Cafe ను అన్ఇన్స్టాల్ చేసినా ఈ ఫైళ్లు ఈ కంప్యూటర్లోనే ఉంటాయి మరియు అవి ఎన్క్రిప్ట్ చేయబడవు.", + "localBackupLast": "చివరి బ్యాకప్: {time}", + "localBackupNone": "ఇంకా బ్యాకప్ లేదు", + "localBackupUpdateFailed": "బ్యాకప్ సెట్టింగ్ను అప్డేట్ చేయడం సాధ్యం కాలేదు", + "localBackupLoadFailed": "బ్యాకప్ సెట్టింగ్ను లోడ్ చేయడం సాధ్యం కాలేదు", + "backupKindAuto": "ఆటో", + "backupSchemaVersion": "స్కీమా v{version}", + "billContent": "బిల్ కంటెంట్", + "billContentHint": "డేటా అందుబాటులో ఉన్నప్పుడు మాత్రమే ప్రారంభించబడిన వివరాలు ప్రింట్ అవుతాయి.", + "deliveryCustomerPhoneWarning": "ఈ ఎంపిక ఆన్లో ఉన్నప్పుడు, కస్టమర్ నంబర్ ఆఫ్లో ఉన్నప్పటికీ డెలివరీ ఆర్డర్లు మరియు కొరియర్ స్లిప్లలో కస్టమర్ నంబర్ కనిపిస్తుంది. కస్టమర్కు కాల్ చేయడానికి కొరియర్కు ఇది అవసరం.", + "deliveryShowCustomerPhoneAlways": "డెలివరీ ఆర్డర్లు మరియు కొరియర్ స్లిప్లలో కస్టమర్ నంబర్ను చూపించు", + "deliveryShowCustomerPhoneAlwaysHint": "డెలివరీ ఆర్డర్లు మరియు కొరియర్ స్లిప్లను నియంత్రిస్తుంది. డెలివరీ ఆర్డర్లకు కూడా కస్టమర్ నంబర్ సెట్టింగ్ నిర్ణయించేలా దీన్ని ఆఫ్ చేయండి.", + "billTemplate": "బిల్ టెంప్లేట్", + "billTemplateClassicDesc": "కస్టమర్ పేరు/మొబైల్, యాడ్-ఆన్ వివరాలు, తగ్గింపులు మరియు సంపాదించిన/బ్యాలెన్స్ లాయల్టీ పాయింట్లతో వ్యక్తిగతీకరించిన లేఅవుట్. డైన్-ఇన్ కోసం ఉత్తమమైనది.", + "billTemplateClassicName": "క్లాసిక్", + "billTemplateCompactDesc": "కనీస, వేగవంతమైన లేఅవుట్. ప్రతి ఐటెమ్కు ఒక లైన్. క్విక్ సర్వీస్ మరియు టేక్అవే కోసం అనువైనది.", + "billTemplateCompactName": "కాంపాక్ట్", + "billTemplateDetailedDesc": "దేశ-నిర్దిష్ట రిజిస్ట్రేషన్ లేబుల్ మరియు విభాగాల వారీ పన్ను వివరాలతో కూడిన వివరణాత్మక పన్ను ఇన్వాయిస్.", + "billTemplateDetailedName": "వివరణాత్మక పన్ను", + "billTemplateMerchantCloned": "కంప్లయన్స్ టెంప్లేట్ నుండి క్లోన్ చేయబడింది", + "billTemplateMerchantCreated": "సృష్టించబడింది", + "billTemplateMerchantDesc": "మీ కస్టమ్ రసీదు లేఅవుట్.", + "billTemplateMerchantImported": "దిగుమతి చేయబడింది", + "billTemplateSaved": "బిల్ టెంప్లేట్ సేవ్ చేయబడింది", + "billingType": "బిల్లింగ్ రకం", + "billingTypePostpaid": "పోస్ట్పెయిడ్ – చెక్అవుట్ వద్ద చెల్లించండి (ఆర్డర్లను హోల్డ్ చేయండి)", + "billingTypePrepaid": "ప్రీపెయిడ్ – ముందుగా చెల్లించండి (హోల్డ్ లేదు)", + "browserWebusb": "బ్రౌజర్ WebUSB", + "builtIn": "అంతర్నిర్మిత", + "businessName": "వ్యాపార పేరు", + "cancel": "రద్దు", + "checkForUpdates": "అప్డేట్ల కోసం తనిఖీ చేయండి", + "checking": "తనిఖీ చేస్తోంది...", + "chooseBackupLocation": "లొకేషన్ ఎంచుకోండి...", + "chooseTemplate": "టెంప్లేట్ ఎంచుకోండి", + "close": "మూసివేయి", + "cloudAccountLoadError": "లోకల్ API కనెక్షన్ను తనిఖీ చేసి మళ్లీ ప్రయత్నించండి. క్లౌడ్ ఖాతాలో ఎలాంటి మార్పులు చేయబడలేదు.", + "cloudAccountLoadFailed": "క్లౌడ్ ఖాతా స్థితిని లోడ్ చేయడం సాధ్యం కాలేదు", + "cloudAccountUnavailable": "క్లౌడ్ ఖాతా సేవలు ప్రస్తుతం అందుబాటులో లేవు", + "cloudAllStopped": "అన్ని క్లౌడ్ సేవలు మరియు టెలిమెట్రీ నిలిపివేయబడ్డాయి", + "cloudCancelDeletion": "తొలగింపు అభ్యర్థనను రద్దు చేయండి", + "cloudCancelDeletionTitle": "క్లౌడ్ తొలగింపు అభ్యర్థనను రద్దు చేయండి", + "cloudConfirmDeletion": "క్లౌడ్ తొలగింపు అభ్యర్థనను నిర్ధారించండి", + "cloudDataDeleted": "క్లౌడ్ డేటా తొలగించబడింది", + "cloudDataDeletedHint": "FloCafe సర్వర్ల నుండి క్లౌడ్ డేటా తొలగించబడింది. ఈ ఇన్స్టాలేషన్లో క్లౌడ్ సేవలను మళ్లీ ప్రారంభించలేరు.", + "cloudDeleteDataButton": "క్లౌడ్ డేటా తొలగింపును అభ్యర్థించండి", + "cloudDeletePrompt": "ఇది మాన్యువల్ సమీక్ష కోసం FloAdmin కు తొలగింపు అభ్యర్థనను సమర్పిస్తుంది మరియు ఇక్కడ క్లౌడ్ సేవలను వెంటనే నిలిపివేస్తుంది. ఆమోదం తర్వాత, స్టోర్-లింక్డ్ సర్వర్ డేటా శాశ్వతంగా తొలగించబడుతుంది. లోకల్ POS డేటా ఈ పరికరంలోనే ఉంటుంది. కొనసాగించడానికి DELETE CLOUD DATA అని టైప్ చేయండి.", + "cloudDeletionCancelFailed": "తొలగింపు అభ్యర్థనను రద్దు చేయడం సాధ్యం కాలేదు", + "cloudDeletionCancelled": "క్లౌడ్ తొలగింపు అభ్యర్థన రద్దు చేయబడింది. మీరు స్వయంగా మళ్లీ ప్రారంభించే వరకు క్లౌడ్ సేవలు ఆఫ్లోనే ఉంటాయి.", + "cloudDeletionFailed": "క్లౌడ్ తొలగింపు అభ్యర్థన విఫలమైంది", + "cloudDeletionFailedHint": "క్లౌడ్ తొలగింపు అభ్యర్థనపై దృష్టి పెట్టాలి. గోప్యతా నియంత్రణల నుండి దాని స్థితిని రిఫ్రెష్ చేయండి లేదా అభ్యర్థనను మళ్లీ ప్రయత్నించండి.", + "cloudDeletionFailedHint2": "తొలగింపు అభ్యర్థన విఫలమైంది. మీరు క్రింది గోప్యతా నియంత్రణల నుండి దాని స్థితిని రిఫ్రెష్ చేయవచ్చు లేదా అభ్యర్థనను మళ్లీ ప్రయత్నించవచ్చు.", + "cloudDeletionPending": "క్లౌడ్ తొలగింపు అభ్యర్థన పెండింగ్లో ఉంది", + "cloudDeletionPendingHint": "క్లౌడ్ తొలగింపు అభ్యర్థన సమీక్ష కోసం పెండింగ్లో ఉంది. క్లౌడ్ సేవలను మళ్లీ ప్రారంభించే ముందు దాన్ని రద్దు చేయండి లేదా సమీక్ష కోసం వేచి ఉండండి.", + "cloudDeletionProcessing": "క్లౌడ్ తొలగింపు ప్రాసెస్ అవుతోంది", + "cloudDeletionProcessingHint": "క్లౌడ్ తొలగింపు ప్రాసెస్ చేయబడుతోంది. దాని స్థితిని రిఫ్రెష్ చేయండి లేదా రద్దు అందుబాటులో ఉంటే రద్దు చేయండి.", + "cloudDeletionProcessingHint2": "క్లౌడ్ తొలగింపు ప్రాసెస్ చేయబడుతోంది. దాని స్థితిని రిఫ్రెష్ చేయండి లేదా రద్దు అందుబాటులో ఉంటే రద్దు చేయండి.", + "cloudDeletionRequest": "తొలగింపు అభ్యర్థన: {status}", + "cloudDeletionStatusRefreshFailed": "క్లౌడ్ తొలగింపు స్థితిని రిఫ్రెష్ చేయడం సాధ్యం కాలేదు", + "cloudDeletionStatusRefreshed": "క్లౌడ్ తొలగింపు స్థితి రిఫ్రెష్ చేయబడింది", + "cloudDeletionSubmitted": "మాన్యువల్ సమీక్ష కోసం క్లౌడ్ తొలగింపు అభ్యర్థన సమర్పించబడింది. ఈ పరికరంలో క్లౌడ్ సేవలు నిలిపివేయబడ్డాయి.", + "cloudEnableButton": "క్లౌడ్ సేవలను ప్రారంభించండి", + "cloudEnableHintAccount": "క్లౌడ్ ఖాతా ఫీచర్లను ఉపయోగించడానికి మొబైల్ యాక్సెస్ నుండి క్లౌడ్ సేవలను ప్రారంభించండి.", + "cloudInitializeAccept": "అంగీకరించి ప్రారంభించండి", + "cloudInitializeButton": "క్లౌడ్ సేవలను ప్రారంభించండి", + "cloudInitializeDialogBody": "ఉత్పత్తిని మెరుగుపరచడానికి డయాగ్నస్టిక్ మరియు వినియోగ డేటా సేకరణను అనుమతించండి.", + "cloudInitializeDialogBody2": "ఇది ప్రాథమిక టెలిమెట్రీని ప్రారంభిస్తుంది మరియు రిమోట్ రిపోర్టింగ్ మరియు సింక్ కోసం FloAdmin క్లౌడ్ సర్వర్లతో కమ్యూనికేట్ చేయడానికి మీ లోకల్ డేటాబేస్ను సిద్ధం చేస్తుంది.", + "cloudInitializeDialogTitle": "క్లౌడ్ సేవలను ప్రారంభించండి", + "cloudManagedAutomatically": "క్లౌడ్ రిజిస్ట్రేషన్ API కీ మరియు స్టోర్ ID ని ఆటోమేటిక్గా నిర్వహిస్తుంది. ఇవి యూజర్ సవరించగల సెట్టింగ్లు కానందున ఉద్దేశపూర్వకంగా దాచబడ్డాయి.", + "cloudPendingVerification": "ధృవీకరణ పెండింగ్లో ఉంది", + "cloudPrefMarketing": "మార్కెటింగ్ సందేశాలు, ఆఫర్లు మరియు సర్వేలు", + "cloudPrefNote": "అత్యవసర సేవా మరియు భద్రతా నోటీసులు ఈ ఐచ్ఛిక సబ్స్క్రిప్షన్ల నుండి వేరుగా ఉంటాయి.", + "cloudPrefProductUpdates": "ఉత్పత్తి అప్డేట్లు మరియు రిలీజ్ నోట్స్", + "cloudPrivacyControls": "క్లౌడ్ గోప్యతా నియంత్రణలు", + "cloudRefreshDeletion": "తొలగింపు స్థితిని రిఫ్రెష్ చేయండి", + "cloudRefreshingDeletion": "రిఫ్రెష్ అవుతోంది…", + "cloudRegistrationFailed": "రిజిస్ట్రేషన్ విఫలమైంది — మీ కనెక్షన్ను తనిఖీ చేయండి", + "cloudRegistrationPending": "అభ్యర్థన పంపబడింది — మీ API కీ 7 రోజుల్లోపు ఇమెయిల్ ద్వారా వస్తుంది. అది వర్తింపజేయబడిన వెంటనే RevFlo నివేదికలు మరియు ఇతర ఫీచర్లు అన్లాక్ అవుతాయి.", + "cloudRegistrationSuccess": "FloAdmin తో నమోదు చేయబడింది", + "cloudResumeHint": "క్లౌడ్ సేవలను తిరిగి ప్రారంభించడానికి క్రింద క్లౌడ్ సేవలను ప్రారంభించి మార్పులను సేవ్ చేయండి.", + "cloudResumeHintStopped": "ఈ పరికరంలో క్లౌడ్ సేవలు మరియు బిల్ సింక్ను తిరిగి ప్రారంభించండి.", + "cloudSaveFailed": "క్లౌడ్ సెట్టింగ్లను సేవ్ చేయడం విఫలమైంది", + "cloudSaved": "క్లౌడ్ సింక్ సెట్టింగ్లు సేవ్ చేయబడ్డాయి", + "cloudSendVerificationEmail": "ధృవీకరణ ఇమెయిల్ పంపండి", + "cloudSendingVerification": "పంపుతోంది…", + "cloudServicesDisabled": "క్లౌడ్ సేవలు నిలిపివేయబడ్డాయి", + "cloudServicesDisabledHint": "రిమోట్ సేల్స్ రిపోర్టింగ్, బిల్ సింక్ మరియు ఆన్లైన్ డ్యాష్బోర్డ్ యాక్సెస్ను ప్రారంభించడానికి క్లౌడ్ సేవలను ప్రారంభించండి.", + "cloudServicesStopped": "క్లౌడ్ సేవలు ఆపివేయబడ్డాయి", + "cloudServicesStoppedHint": "తొలగింపు అభ్యర్థన పరిష్కరించబడే వరకు క్లౌడ్ సేవలు ఆపివేయబడే ఉంటాయి.", + "cloudStatusUnavailable": "స్థితి అందుబాటులో లేదు", + "cloudStopAllButton": "అన్ని క్లౌడ్ సేవలను ఆపివేయండి", + "cloudStopAllConfirm": "ఈ పరికరంలో అన్ని FloCafe క్లౌడ్ సేవలు, గుర్తించబడిన డయాగ్నస్టిక్స్ మరియు భవిష్యత్తు టెలిమెట్రీని ఆపివేయాలా? లోకల్ POS డేటా అందుబాటులోనే ఉంటుంది.", + "cloudStopFailed": "క్లౌడ్ సేవలను ఆపివేయడం సాధ్యం కాలేదు", + "cloudStopReversible": "క్లౌడ్ సేవలను ఆపివేయడం తిరిగి మార్చదగినది. డేటా శాశ్వతంగా తొలగించబడే ముందు క్లౌడ్ తొలగింపు అభ్యర్థన FloAdmin లో మాన్యువల్గా సమీక్షించబడుతుంది. ఈ రెండు చర్యల్లో ఏదీ మీ లోకల్ ఆర్డర్లు, బిల్లులు, కస్టమర్లు, ఉత్పత్తులు లేదా డేటాబేస్ను తొలగించదు.", + "cloudTelemetryNote": "మీరు మీ ఇమెయిల్కు లింక్ చేయడానికి ఎంచుకున్న వినియోగ డేటా ఆ ఖాతాతోనే ఉంటుంది. ఈ చర్య భవిష్యత్తు టెలిమెట్రీ మొత్తాన్ని ఆపివేస్తుంది మరియు వినియోగ పింగ్లు ఉపయోగించే అజ్ఞాత ఐడెంటిఫైయర్ను మారుస్తుంది.", + "cloudUnavailableBadge": "అందుబాటులో లేదు", + "cloudVerificationHint": "ఉత్పత్తి సేవా నోటీసులు, భద్రతా అప్డేట్లు మరియు ఇతర ఖాతా కమ్యూనికేషన్ కోసం ధృవీకరణ ముఖ్యం.", + "cloudVerified": "ధృవీకరించబడింది", + "codeExpires": "{date} న గడువు ముగుస్తుంది", + "codeGenerated": "{date} న రూపొందించబడింది", + "comingSoon": "త్వరలో వస్తోంది", + "configuredPrinters": "కాన్ఫిగర్ చేయబడిన ప్రింటర్లు", + "confirmBackupTitle": "బ్యాకప్ను నిర్ధారించండి", + "confirmButton": "నిర్ధారించండి", + "confirmDeleteBackupTitle": "బ్యాకప్ను తొలగించండి", + "confirmImportTitle": "దిగుమతిని నిర్ధారించండి", + "confirmPin": "PIN నిర్ధారించండి", + "confirmRestoreTitle": "పునరుద్ధరణను నిర్ధారించండి", + "confirmationPhraseMismatch": "నిర్ధారణ వాక్యం సరిపోలలేదు", + "connectedToFloadmin": "FloAdmin కు కనెక్ట్ చేయబడింది", + "connectionFailed": "కనెక్షన్ విఫలమైంది — కీ మరియు సర్వర్ను తనిఖీ చేయండి", + "connectionNetwork": "నెట్వర్క్ (IP/TCP)", + "connectionType": "కనెక్షన్ రకం", + "connectionUsb": "USB", + "connectionWebusb": "WebUSB (బ్రౌజర్)", + "cashDrawerPulse": "చెక్అవుట్ వద్ద క్యాష్ డ్రాయర్ తెరవండి", + "cashDrawerPulseEnabledShort": "క్యాష్ డ్రాయర్", + "cashDrawerPulseHint": "ప్రతి ప్రింట్ చేసిన బిల్ తర్వాత ఈ రసీదు ప్రింటర్ ద్వారా ESC/POS డ్రాయర్ పల్స్ పంపుతుంది.", + "noCountersConfigured": "ఇంకా కౌంటర్లు కాన్ఫిగర్ చేయబడలేదు.", + "sendPulseToCashDrawer": "క్యాష్ డ్రాయర్కు పల్స్ పంపండి", + "sendPulseToCashDrawerHint": "చెక్అవుట్ పూర్తయినప్పుడు కనెక్ట్ చేయబడిన క్యాష్ డ్రాయర్ను తెరుస్తుంది.", + "cashDrawerPulsePaymentOptions": "ఈ చెల్లింపు పద్ధతుల కోసం డ్రాయర్ తెరవండి", + "cashDrawerPulsePaymentOptionsHint": "డ్రాయర్ తెరవడానికి నగదు మరియు కార్డును ఎంచుకోండి. UPI డిఫాల్ట్గా ఎంచుకోబడదు మరియు అది డ్రాయర్ను తెరవదు.", + "paymentMethodCash": "నగదు", + "paymentMethodCard": "కార్డు", + "paymentMethodUpi": "UPI", + "contactEmailTitle": "సంప్రదింపు ఇమెయిల్", + "copyCode": "కోడ్ కాపీ చేయండి", + "couldNotSavePreference": "ప్రాధాన్యతను సేవ్ చేయడం సాధ్యం కాలేదు", + "country": "దేశం", + "countrySavedTaxPluginFailed": "దేశం సేవ్ చేయబడింది, కానీ దాని పన్ను ప్లగిన్ ఇన్స్టాల్ చేయడం సాధ్యం కాలేదు. ఇది పరిష్కరించబడే వరకు పన్నులు ప్రారంభించబడే ఉంటాయి.", + "createBackup": "బ్యాకప్ సృష్టించండి", + "createBackupHint": "యూజర్లు, PINలు, సెట్టింగ్లు, ఆర్డర్లు, ఉత్పత్తులు మరియు చరిత్రను భద్రపరిచే పూర్తి .db బ్యాకప్ను సృష్టించండి. FloCafe ను మరో కంప్యూటర్కు తరలించడానికి దీన్ని ఉపయోగించండి.", + "currency": "కరెన్సీ", + "currencyAutoFilled": "కరెన్సీ (ఆటో-ఫిల్ చేయబడింది)", + "currencyRecommended": "సిఫార్సు చేయబడినది", + "currencyPopular": "ప్రసిద్ధ కరెన్సీలు", + "currencyAll": "అన్ని కరెన్సీలు", + "currencySelectionHint": "సిఫార్సు చేయబడిన కరెన్సీ ఎంచుకున్న దేశానికి సరిపోలుతుంది, కానీ మీరు మరొకదాన్ని ఎంచుకోవచ్చు.", + "currencyChangeTitle": "కరెన్సీని {currency} కు మార్చాలా?", + "currencyChangeExistingData": "ఈ స్టోర్ ప్రస్తుతం {currency} ఉపయోగిస్తోంది మరియు ఆ కరెన్సీలో {invoices} ఇన్వాయిస్లు మరియు {orders} ఆర్డర్లు నమోదై ఉన్నాయి.", + "currencyChangeDestructiveBody": "{currency} కు మార్చడం వల్ల గత మొత్తాలను సురక్షితంగా మార్చలేము. FloCafe లోకల్ డేటాబేస్ను మళ్లీ ప్రారంభించాలి మరియు ఆర్డర్లు, ఇన్వాయిస్లు, చెల్లింపులు, రీఫండ్లు, కస్టమర్లు, నివేదికలు, ఇన్వెంటరీ చరిత్ర, సిబ్బంది ఖాతాలు మరియు సెట్టింగ్లను శాశ్వతంగా తొలగించాలి.", + "currencyChangeMenuBody": "మెనూ నిర్మాణం అలాగే ఉంటుంది, కానీ అన్ని ఉత్పత్తుల ధరలు, ఉత్పత్తి ఖర్చులు మరియు యాడ్-ఆన్ ధరలు సున్నాకి రీసెట్ చేయబడతాయి.", + "currencyChangeBackupBody": "ముందుగా పూర్తి రికవరీ బ్యాకప్ ఆటోమేటిక్గా సృష్టించబడుతుంది. ఇప్పటికే ఉన్న బాహ్య బ్యాకప్లు లేదా రిమోట్ క్లౌడ్ డేటా తొలగించబడవు.", + "currencyChangeTypeConfirm": "కొనసాగించడానికి {phrase} అని టైప్ చేయండి", + "currencyChangeConfirmButton": "{currency} కు మార్చి మళ్లీ ప్రారంభించండి", + "currencyChangePinPrompt": "కరెన్సీని మార్చడానికి మరియు లోకల్ డేటాబేస్ను మళ్లీ ప్రారంభించడానికి పరికర మాస్టర్ PIN నమోదు చేయండి.", + "currencyImpactFailed": "డేటాబేస్ను తనిఖీ చేయడం సాధ్యం కాలేదు. కరెన్సీని సురక్షితంగా మార్చలేము.", + "currencyResetFailed": "కరెన్సీ మార్పు విఫలమైంది", + "currencyResetComplete": "కరెన్సీ మార్చబడింది. సెటప్కు దారి మళ్లిస్తోంది…", + "customerMandatory": "కస్టమర్ తప్పనిసరి", + "customerMandatoryDisabled": "తప్పనిసరి కస్టమర్ నిలిపివేయబడింది", + "customerMandatoryEnabled": "తప్పనిసరి కస్టమర్ ప్రారంభించబడింది", + "customerMandatoryHint": "ఆర్డర్ వేసే ముందు కస్టమర్ ఎంపికను తప్పనిసరి చేయండి", + "databaseExported": "డేటాబేస్ విజయవంతంగా ఎగుమతి చేయబడింది", + "databaseHealthCheck": "డేటాబేస్ హెల్త్ చెక్", + "databaseHealthCheckDescription": "ఈ డేటాబేస్ నిర్మాణాన్ని యాప్ ఆశించే దానితో పోల్చి, పరిష్కారాలను సూచిస్తుంది — ఏదైనా మారకముందే ప్రతి దానికి డేటా కోల్పోయే ప్రమాదాన్ని చూపుతుంది.", + "databaseInformation": "డేటాబేస్ సమాచారం", + "databaseTables": "డేటాబేస్ టేబుళ్లు", + "dbInitializedRedirecting": "డేటాబేస్ ప్రారంభించబడింది. సెటప్కు దారి మళ్లిస్తోంది...", + "default": "డిఫాల్ట్", + "defaultPrinter": "డిఫాల్ట్", + "defaultPrinterSet": "డిఫాల్ట్ ప్రింటర్ సెట్ చేయబడింది", + "defaultPrinterTipBody": "KOT మరియు బిల్ ఆటో-ప్రింట్ కోసం డిఫాల్ట్ ప్రింటర్ ఉపయోగించబడుతుంది. ఒక ప్రింటర్ను డిఫాల్ట్గా సెట్ చేసి, ఆపై ప్రింట్ ఎంపికలలో ఆటో-ప్రింట్ కాన్ఫిగర్ చేయండి.", + "defaultPrinterTipTitle": "చిట్కా:", + "delete": "తొలగించు", + "deleteBackup": "తొలగించు", + "deleteBackupConfirm": "బ్యాకప్ {fileName} ను తొలగించాలా? దీన్ని రద్దు చేయలేరు.", + "deletePaymentMethodConfirm": "ఈ ఉపయోగించని చెల్లింపు పద్ధతిని తొలగించాలా?", + "devModeDisabled": "డెవలప్మెంట్ మోడ్లో అప్డేట్ తనిఖీ నిలిపివేయబడింది.", + "directIp": "డైరెక్ట్ IP (సిఫార్సు చేయబడినది)", + "discard": "విస్మరించు", + "disconnectDevicesWarning": "కొత్త కోడ్ రూపొందించడం వల్ల ప్రస్తుతం జత చేయబడిన అన్ని పరికరాలు డిస్కనెక్ట్ అవుతాయి.", + "discountBoth": "రెండూ (% మరియు స్థిర మొత్తం)", + "discountFlatOnly": "స్థిర మొత్తం మాత్రమే", + "discountLimits": "తగ్గింపు పరిమితులు", + "discountMode": "తగ్గింపు మోడ్", + "discountModeFlat": "స్థిర మొత్తం మాత్రమే", + "discountModeHint": "ఏ తగ్గింపు రకాలు అందుబాటులో ఉంటాయి", + "discountModePercentage": "శాతం మాత్రమే", + "discountNone": "నిలిపివేయబడింది (తగ్గింపులు లేవు)", + "discountPercentageOnly": "శాతం మాత్రమే", + "discountSaved": "తగ్గింపు సెట్టింగ్లు సేవ్ చేయబడ్డాయి", + "discounts": "తగ్గింపులు", + "downloadForAndroid": "Android కోసం డౌన్లోడ్ చేయండి", + "downloadForIos": "iOS కోసం డౌన్లోడ్ చేయండి", + "edit": "సవరించు", + "editPrinter": "ప్రింటర్ సవరించు", + "editStation": "స్టేషన్ సవరించు", + "email": "ఇమెయిల్", + "enableBillSync": "RevFlo కోసం క్లౌడ్ సింక్ను ప్రారంభించండి", + "enableBillSyncHint": "RevFlo మొబైల్ రిపోర్టింగ్ మరియు పరికర జత చేయడం వంటి క్లౌడ్ ఫీచర్ల కోసం FloAdmin తో సురక్షితంగా కమ్యూనికేట్ చేయడానికి FloCafe ను అనుమతించండి. ఈ ఫీచర్లకు అవసరమైన సమాచారం FloAdmin ద్వారా మీ అధీకృత పరికరాలకు పంపబడవచ్చు. క్లౌడ్ సింక్ ఐచ్ఛికం మరియు డిఫాల్ట్గా నిలిపివేయబడి ఉంటుంది.", + "enableLoyalty": "లాయల్టీ ప్రోగ్రామ్ను ప్రారంభించండి", + "enableLoyaltyProgram": "లాయల్టీ ప్రోగ్రామ్ను ప్రారంభించండి", + "enableOnlineOrderPolling": "OrderFlow నుండి ఆన్లైన్ ఆర్డర్ పోలింగ్ను ప్రారంభించండి", + "enablePrinter": "ప్రింటర్ను ప్రారంభించండి", + "enablePrinterHint": "USB/Bluetooth ద్వారా థర్మల్ ప్రింటర్కు కనెక్ట్ చేయండి", + "enableWhatsapp": "WhatsApp షేర్ ప్రారంభించండి", + "enableWhatsappHint": "చెల్లింపు తర్వాత WhatsApp ద్వారా బిల్ వివరాలను పంపండి", + "enableWhatsappShare": "WhatsApp షేర్ ప్రారంభించండి", + "enableWhatsappShareHint": "చెల్లింపు తర్వాత WhatsApp ద్వారా బిల్ వివరాలను పంపండి", + "enforcePhoneLength": "ఫోన్ నంబర్ పొడవును తప్పనిసరి చేయండి", + "enforcePhoneLengthDisabled": "ఫోన్ పొడవు నియమం నిలిపివేయబడింది", + "enforcePhoneLengthEnabled": "ఫోన్ పొడవు నియమం ప్రారంభించబడింది", + "enforcePhoneLengthHint": "మీ దేశానికి చెల్లుబాటు అయ్యే ఫోన్ నంబర్ టైప్ చేసిన వెంటనే ఆటోమేటిక్గా పేరు ఫీల్డ్కు వెళ్తుంది — ఉదా. భారతదేశానికి 10 అంకెలు.", + "enterMasterPinPrompt": "కొనసాగించడానికి మీ పరికర మాస్టర్ PIN నమోదు చేయండి.", + "exportDatabase": "సవరించిన JSON ను ఎగుమతి చేయండి", + "exportDatabaseHint": "సపోర్ట్ లేదా పాక్షిక డేటా బదిలీ కోసం పోర్టబుల్ JSON డేటా ఫైల్ను ఎగుమతి చేయండి. పాస్వర్డ్లు, PINలు, క్లౌడ్ సీక్రెట్లు మరియు కొన్ని ప్రైవేట్ టేబుళ్లు ఉద్దేశపూర్వకంగా తొలగించబడతాయి, కాబట్టి పూర్తి కంప్యూటర్ మైగ్రేషన్ కోసం ఇది ఉత్తమ ఎంపిక కాదు.", + "exportFailed": "ఎగుమతి విఫలమైంది", + "exportToJson": "JSON కు ఎగుమతి చేయండి", + "financialYearStartDay": "ఆర్థిక సంవత్సరం ప్రారంభ రోజు", + "financialYearStartMonth": "ఆర్థిక సంవత్సరం ప్రారంభ నెల", + "firstPaired": "{date} న జత చేయబడింది", + "fixesApplied": "{count, plural, one {# పరిష్కారం వర్తింపజేయబడింది} other {# పరిష్కారాలు వర్తింపజేయబడ్డాయి}}", + "fixesAppliedPartial": "{applied} పరిష్కారాలు వర్తింపజేయబడ్డాయి, {failed} విఫలమయ్యాయి", + "floadminSalesReporting": "FloAdmin — సేల్స్ రిపోర్టింగ్", + "floadminSalesReportingHint": "RevFlo మొబైల్ రిపోర్టింగ్ మరియు పరికర జత చేయడం వంటి ఫీచర్లను ప్రారంభించడానికి FloCafe ను FloAdmin తో కనెక్ట్ చేయండి.", + "footerMessage": "ఫుటర్ సందేశం", + "footerMessageHint": "ప్రతి బిల్ దిగువన ప్రింట్ చేయబడుతుంది", + "footerMessagePlaceholder": "ఉదా. విచ్చేసినందుకు ధన్యవాదాలు!", + "general": "సాధారణ", + "generateNewCode": "కొత్త కోడ్ రూపొందించండి", + "generatePairingCode": "జత చేసే కోడ్ రూపొందించండి", + "generating": "రూపొందిస్తోంది...", + "globalLoyaltyRate": "గ్లోబల్ సంపాదన రేటు", + "globalLoyaltyRateHint": "కస్టమ్ రేటు సెట్ చేయని ఉత్పత్తులకు వర్తించే డిఫాల్ట్ రేటు.", + "googleDrive": "Google Drive బ్యాకప్లు", + "googleDriveAccount": "ఖాతా", + "googleDriveBackingUp": "బ్యాకప్ అవుతోంది...", + "googleDriveBackupFailed": "Google Drive కు బ్యాకప్ విఫలమైంది", + "googleDriveBackupNow": "ఇప్పుడే Drive కు బ్యాకప్ చేయండి", + "googleDriveBackupSuccess": "బ్యాకప్ Google Drive కు అప్లోడ్ చేయబడింది", + "googleDriveConnect": "Google Drive కనెక్ట్ చేయండి", + "googleDriveReauthenticate": "Google Drive ను మళ్లీ ధృవీకరించండి", + "googleDriveConnectFailed": "Google Drive కు కనెక్ట్ చేయడం సాధ్యం కాలేదు", + "googleDriveConnected": "కనెక్ట్ చేయబడింది", + "googleDriveConnectedSuccess": "Google Drive కనెక్ట్ చేయబడింది", + "googleDriveConnecting": "కనెక్ట్ అవుతోంది...", + "googleDriveDisconnect": "డిస్కనెక్ట్ చేయండి", + "googleDriveDisconnectConfirm": "Google Drive డిస్కనెక్ట్ చేయాలా? ఇది మీ Drive ఖాతాకు FloCafe యాక్సెస్ను రద్దు చేస్తుంది మరియు షెడ్యూల్ చేసిన బ్యాకప్లను ఆపివేస్తుంది.", + "googleDriveDisconnectFailed": "Google Drive డిస్కనెక్ట్ చేయడం విఫలమైంది", + "googleDriveDisconnectedSuccess": "Google Drive డిస్కనెక్ట్ చేయబడింది", + "googleDriveDisconnecting": "డిస్కనెక్ట్ అవుతోంది...", + "googleDriveRetryDisconnect": "డిస్కనెక్ట్ మళ్లీ ప్రయత్నించండి", + "googleDriveRevokePending": "Google Drive యాక్సెస్ ఇంకా యాక్టివ్గానే ఉంది. దాన్ని రద్దు చేయడానికి డిస్కనెక్ట్ మళ్లీ ప్రయత్నించండి.", + "googleDriveFrequency": "బ్యాకప్ ఫ్రీక్వెన్సీ", + "googleDriveFrequencyDaily": "రోజువారీ", + "googleDriveFrequencyWeekly": "వారానికొకసారి", + "googleDriveHint": "ఈ పరికరం నుండి డేటాబేస్ బ్యాకప్లను మీ Google Drive లోని ప్రత్యేక ఫోల్డర్కు ఆటోమేటిక్గా అప్లోడ్ చేయండి.", + "googleDriveLastBackup": "చివరి Drive బ్యాకప్", + "googleDriveLastBackupErrorAt": "చివరి Drive బ్యాకప్ ప్రయత్నం {time} న విఫలమైంది", + "googleDriveLastBackupNever": "ఎప్పుడూ లేదు", + "googleDriveLastBackupSuccessAt": "చివరిగా {time} న Drive కు బ్యాకప్ చేయబడింది", + "googleDriveNotConfigured": "ఈ బిల్డ్ కోసం Google Drive ఇంటిగ్రేషన్ కాన్ఫిగర్ చేయబడలేదు", + "googleDriveNotConfiguredHint": "ఈ బిల్డ్ కోసం GOOGLE_DRIVE_CLIENT_ID మరియు GOOGLE_DRIVE_CLIENT_SECRET సెట్ చేయమని మెయింటెయినర్ను అడగండి. docs/google-drive-setup.md చూడండి.", + "googleDriveNotConnected": "కనెక్ట్ కాలేదు", + "googleDriveRetention": "చివరి N బ్యాకప్లను ఉంచండి", + "googleDriveRetentionHint": "ఈ సంఖ్యకు మించిన పాత ఆటోమేటిక్ బ్యాకప్లు Drive ట్రాష్కు తరలించబడతాయి. మాన్యువల్ బ్యాకప్లు శాశ్వతంగా ఉంచబడతాయి. ఇది లోకల్ బ్యాకప్ చరిత్రను తొలగించదు.", + "googleDriveSavePreferencesFailed": "Google Drive సెట్టింగ్లను సేవ్ చేయడం విఫలమైంది", + "googleDriveSecureStorageUnavailable": "ఈ పరికరంలో సురక్షిత స్టోరేజ్ అందుబాటులో లేదు, కాబట్టి Google Drive కనెక్షన్లను ఇక్కడ సురక్షితంగా నిల్వ చేయలేము.", + "googleDriveUnencryptedWarning": "Google Drive కాపీలు పూర్తి SQLite డేటాబేస్ బ్యాకప్లు మరియు ఇంకా FloCafe ద్వారా ఎన్క్రిప్ట్ చేయబడలేదు. వాటిలో కస్టమర్, సిబ్బంది, ధృవీకరణ మరియు సెట్టింగ్ల డేటా ఉండవచ్చు. ఎంచుకున్న Drive ఖాతా లేదా ఫోల్డర్కు యాక్సెస్ ఉన్న ఎవరైనా వాటిని యాక్సెస్ చేయవచ్చు; FloCafe మాస్టర్ PIN పోర్టబుల్ ఎన్క్రిప్షన్ కీ కాదు.", + "googleDrivePrivacyWarningTitle": "ముఖ్యమైన Google Drive బ్యాకప్ హెచ్చరిక", + "googleDrivePrivacyAcknowledgement": "కొనసాగే ముందు, ఇది పూర్తి SQLite డేటాబేస్ బ్యాకప్ అని, ఇంకా FloCafe ద్వారా ఎన్క్రిప్ట్ చేయబడలేదని మరియు ఎంచుకున్న Google Drive ఖాతా లేదా ఫోల్డర్కు యాక్సెస్ ఉన్న ఎవరికైనా అందుబాటులో ఉండవచ్చని అంగీకరించండి. FloCafe మాస్టర్ PIN క్లౌడ్ కాపీని ఎన్క్రిప్ట్ చేయదు లేదా అన్లాక్ చేయదు.", + "googleDriveAcknowledge": "నాకు అర్థమైంది", + "googleDriveBackupQueued": "Google Drive బ్యాకప్ క్యూలో పెట్టబడింది", + "googleDriveDestination": "Drive డెస్టినేషన్", + "googleDriveCreateDestination": "కొత్త Drive ఫోల్డర్ సృష్టించండి", + "googleDriveDestinationCreated": "కొత్త Drive డెస్టినేషన్ సృష్టించబడింది", + "googleDriveDestinationCreateFailed": "Drive డెస్టినేషన్ను సృష్ించడం సాధ్యం కాలేదు", + "googleDriveDestinationLoadFailed": "Drive డెస్టినేషన్లను లోడ్ చేయడం సాధ్యం కాలేదు", + "googleDriveDestinationSelectFailed": "Drive డెస్టినేషన్ను ఎంచుకోవడం సాధ్యం కాలేదు", + "googleDriveLastError": "చివరి Drive స్థితి: {code}", + "googleDriveJobStatus": "Drive జాబ్: {state}", + "googleDriveBackupRetryPending": "Google Drive బ్యాకప్ పెండింగ్లో ఉంది మరియు ఆటోమేటిక్గా మళ్లీ ప్రయత్నిస్తుంది.", + "googleDriveRetentionPending": "బ్యాకప్ అప్లోడ్ చేయబడింది, కానీ ఆటోమేటిక్ రిటెన్షన్ క్లీనప్ పెండింగ్లో ఉంది మరియు ఆటోమేటిక్గా మళ్లీ ప్రయత్నిస్తుంది.", + "googleDriveRemoteHistory": "రిమోట్ Drive బ్యాకప్లు", + "googleDriveLoadingRemoteHistory": "లోడ్ అవుతోంది...", + "googleDriveRefreshRemoteHistory": "రిఫ్రెష్", + "googleDriveNoRemoteBackups": "FloCafe కు చెందిన రిమోట్ బ్యాకప్లు ఏవీ కనుగొనబడలేదు.", + "googleDriveRemoteHistoryFailed": "రిమోట్ Drive బ్యాకప్లను లోడ్ చేయడం సాధ్యం కాలేదు", + "googleDriveAutomaticBadge": "ఆటోమేటిక్", + "googleDriveManualBadge": "మాన్యువల్ - శాశ్వతంగా ఉంచబడుతుంది", + "googleDriveRestore": "పునరుద్ధరించు", + "googleDriveRestorePrompt": "కొనసాగించడానికి RESTORE GOOGLE DRIVE BACKUP అని టైప్ చేయండి.", + "googleDriveRestoreTitle": "Google Drive బ్యాకప్ను పునరుద్ధరించండి", + "googleDriveRestoreQueued": "Google Drive పునరుద్ధరణ క్యూలో పెట్టబడింది", + "googleDriveRestoreFailed": "Google Drive పునరుద్ధరణను ప్రారంభించడం సాధ్యం కాలేదు", + "googleDriveRestoreNotice": "పునరుద్ధరించడం వల్ల ప్రస్తుత డేటా మొత్తం భర్తీ చేయబడుతుంది మరియు డేటా భద్రత కోసం Google Drive ఆటోమేటిక్గా డిస్కనెక్ట్ చేయబడుతుంది. ఆ తర్వాత మీరు Google Drive ను మళ్లీ కనెక్ట్ చేయాల్సి ఉంటుంది.", + "googleDrivePermissionNotice": "ముఖ్య గమనిక: Google బ్రౌజర్ విండోలో, Google Drive ఫైల్ యాక్సెస్ కోసం బాక్స్ను తప్పకుండా టిక్ చేయండి.", + "googleDrivePermissionDenied": "Google Drive ఫైల్ అనుమతి మంజూరు చేయబడలేదు. దయచేసి Google సైన్-ఇన్ స్క్రీన్పై అనుమతి చెక్బాక్స్ను టిక్ చేయండి.", + "hardwarePrinters": "హార్డ్వేర్ ప్రింటర్లు", + "healthCheckClean": "సమస్యలు ఏవీ కనుగొనబడలేదు — ఈ డేటాబేస్ ఆశించిన స్కీమాతో సరిపోలుతోంది.", + "healthCheckDescription": "ఈ డేటాబేస్ నిర్మాణాన్ని యాప్ ఆశించే దానితో పోల్చి, తప్పిపోయిన లేదా ఊహించని వాటిని సూచిస్తుంది.", + "healthCheckFailed": "హెల్త్ చెక్ విఫలమైంది", + "healthCheckReviewHeader": "మాన్యువల్ సమీక్ష అవసరం ({count})", + "healthCheckReviewHint": "ఇవి ఎప్పుడూ ఆటోమేటిక్గా వర్తింపజేయబడవు — వీటిలో డేటాను తొలగించడం లేదా కాలమ్ రకాన్ని మార్చడం ఉండవచ్చు, ఈ టూల్ దానంతట అదే ఆ పని చేయదు.", + "healthCheckSafeHeader": "ఆటోమేటిక్గా పరిష్కరించడానికి సురక్షితం ({count})", + "howItWorks": "ఇది ఎలా పనిచేస్తుంది:", + "howItWorksBody": "Flo పోర్ట్ 3001 పై ఎంబెడెడ్ HTTP సర్వర్ను నడుపుతుంది. /kds వద్ద ఉన్న KDS పేజీ రియల్-టైమ్ ఆర్డర్ అప్డేట్ల కోసం WebSocket ద్వారా కనెక్ట్ అవుతుంది. యాప్ ఇన్స్టాల్ అవసరం లేదు — అదే నెట్వర్క్లో ఉన్న ఆధునిక బ్రౌజర్ సరిపోతుంది.", + "importDatabase": "సవరించిన JSON ను దిగుమతి చేయండి", + "importDatabaseHint": "FloCafe JSON ఎగుమతి నుండి డేటాను దిగుమతి చేయండి. Mac-నుండి-Windows లేదా పూర్తి-పరికర మైగ్రేషన్ కోసం, దీని బదులు బ్యాకప్ సృష్టించండి మరియు బ్యాకప్ పునరుద్ధరించండి ఉపయోగించండి.", + "importFailed": "దిగుమతి విఫలమైంది. ఫైల్ FloCafe JSON ఎగుమతి అని మరియు మద్దతు ఉన్న అప్లోడ్ పరిమాణంలోనే ఉందని తనిఖీ చేయండి.", + "importOverwriteConfirm": "మీరు ఇప్పటికే ఉన్న డేటా మొత్తాన్ని భర్తీ చేయాలనుకుంటున్నారా? దాని బదులు విలీనం చేయడానికి రద్దు క్లిక్ చేయండి.", + "importSuccess": "డేటాబేస్ విజయవంతంగా దిగుమతి చేయబడింది", + "initializeDatabase": "డేటాబేస్ను ప్రారంభించండి", + "initializeDatabaseButton": "డేటాబేస్ను ప్రారంభించండి…", + "initializeDatabaseDescription": "ప్రతి ఉత్పత్తి, ఆర్డర్, కస్టమర్ మరియు సెట్టింగ్ను శాశ్వతంగా తుడిచివేసి, ఖాళీ ఇన్స్టాల్కు రీసెట్ చేస్తుంది. అంతకు ముందే ఆటోమేటిక్గా ఒక బ్యాకప్ సృష్టించబడుతుంది.", + "initializeDialogBackup": "ఏదైనా తొలగించబడే ముందు ఆటోమేటిక్గా ఒక బ్యాకప్ సృష్టించబడుతుంది.", + "initializeDialogBody": "ఇది ప్రతి ఉత్పత్తి, ఆర్డర్, కస్టమర్ మరియు సెట్టింగ్ను శాశ్వతంగా తొలగిస్తుంది మరియు డేటాబేస్ను ఖాళీ ఇన్స్టాల్కు రీసెట్ చేస్తుంది. ఆ తర్వాత మీరు మళ్లీ మొదటిసారి సెటప్ పూర్తి చేయాల్సి ఉంటుంది.", + "initializeFailedGeneric": "ప్రారంభించడం విఫలమైంది", + "initializeLocalBackupFailed": "డేటాబేస్ ప్రారంభించబడింది, కానీ ఆటోమేటిక్ బ్యాకప్ ఫోల్డర్లో బ్యాకప్ కాపీని సేవ్ చేయడం సాధ్యం కాలేదు. రీసెట్కు ముందు తీసిన బ్యాకప్ ఇంకా యాప్ డేటా ఫోల్డర్లోనే ఉంది.", + "initializeMasterPinPrompt": "డేటాబేస్ను శాశ్వతంగా ప్రారంభించడానికి మీ పరికర మాస్టర్ PIN నమోదు చేయండి.", + "initializeTypeConfirm": "కొనసాగించడానికి {phrase} అని టైప్ చేయండి", + "instagramHandle": "Instagram హ్యాండిల్", + "instagramHandleHint": "సెట్ చేసి ఉంటే, ప్రింట్ చేసిన బిల్లులపై చూపబడుతుంది", + "instagramHint": "సెట్ చేసి ఉంటే, ప్రింట్ చేసిన బిల్లులపై చూపబడుతుంది", + "instagramPlaceholder": "@yourcafe", + "installedOnThisComputer": "ఈ కంప్యూటర్లో ఇన్స్టాల్ చేయబడింది", + "invalidExportFile": "చెల్లని FloCafe ఎగుమతి ఫైల్", + "invalidPhoneFormat": "చెల్లని ఫోన్ నంబర్ ఫార్మాట్", + "invoiceNumberIncludePeriod": "ఇన్వాయిస్ నంబర్లో కాలాన్ని చేర్చండి", + "invoiceNumberIncludePeriodHint": "ప్రిఫిక్స్ తర్వాత తేదీ, నెల లేదా ఆర్థిక సంవత్సరాన్ని జోడిస్తుంది.", + "invoiceNumberPrefix": "ప్రిఫిక్స్", + "invoiceNumberPrefixInvalid": "ఇన్వాయిస్ ప్రిఫిక్స్ గరిష్టంగా 12 అక్షరాలు మరియు అంకెలు మాత్రమే ఉండాలి", + "invoiceNumberPreview": "ప్రివ్యూ", + "invoiceNumbers": "ఇన్వాయిస్ నంబర్లు", + "invoiceResetDaily": "రోజువారీ", + "invoiceResetFinancialYear": "ఆర్థిక సంవత్సరం", + "invoiceResetMonthly": "నెలవారీ", + "invoiceResetNever": "ఎప్పుడూ వద్దు", + "invoiceResetPeriod": "సిరీస్ రీసెట్", + "ipAddress": "IP చిరునామా *", + "ipAddressPlaceholder": "192.168.1.100", + "iranCalendar": "క్యాలెండర్", + "iranCalendarGregorian": "గ్రెగోరియన్", + "iranCalendarLocale": "ఆటో (షమ్సీ)", + "iranCalendarPersian": "షమ్సీ (పర్షియన్)", + "iranCurrencyDisplay": "కరెన్సీ ప్రదర్శన", + "iranCurrencyDisplayRial": "రియాల్ (ریال)", + "iranCurrencyDisplayToman": "తోమన్ (تومان)", + "iranCurrencyDisplayTomanShort": "తోమన్ సంక్షిప్త రూపం (ت)", + "iranLocaleHint": "ప్రదర్శనకు మాత్రమే — మొత్తాలు రియాల్ (IRR) లోనే నిల్వ చేయబడతాయి.", + "iranLocaleTitle": "ఇరాన్ ప్రదర్శన ప్రాధాన్యతలు", + "iranNumberDigits": "అంకెలు", + "iranNumberDigitsLatin": "లాటిన్ (0-9)", + "iranNumberDigitsLocale": "ఆటో (పర్షియన్)", + "kds": "KDS", + "kdsDefaultView": "డిఫాల్ట్ వ్యూ", + "kdsDefaultViewHint": "చెఫ్లు KDS తెరిచినప్పుడు వారికి కనిపించే వ్యూ. ప్రతి చెఫ్ తమ స్వంత సెషన్ కోసం ట్యాబ్లు ↔ కాన్బాన్ మధ్య మార్చుకోవచ్చు.", + "kdsDefaultViewKanban": "కాన్బాన్ (నిలువు వరుసలు)", + "kdsDefaultViewKanbanHint": "నాలుగు స్థితులు ఒకేసారి కనిపిస్తాయి, స్థితిని అప్డేట్ చేయడానికి నిలువు వరుసల మధ్య ఐటెమ్లను డ్రాగ్ చేయండి.", + "kdsDefaultViewTabs": "ట్యాబ్లు (జాబితా)", + "kdsDefaultViewTabsHint": "ఒకసారి ఒక స్థితి మాత్రమే. స్వల్ప రద్దీ మరియు ఖచ్చితమైన నియంత్రణ కోసం ఉత్తమమైనది.", + "kdsEnabledOff": "కిచెన్ డిస్ప్లే సిస్టమ్ నిలిపివేయబడింది", + "kdsEnabledOn": "కిచెన్ డిస్ప్లే సిస్టమ్ ప్రారంభించబడింది", + "kdsEnabledToggle": "కిచెన్ డిస్ప్లే సిస్టమ్", + "kdsEnabledToggleHint": "కిచెన్ డిస్ప్లేను చూపండి మరియు మీ నెట్వర్క్ ద్వారా పరికరాలను జత చేయడానికి అనుమతించండి. ఈ వ్యాపారం KDS ఉపయోగించకపోతే దీన్ని ఆఫ్ చేయండి.", + "kdsInfoFetchFailed": "KDS సమాచారాన్ని పొందడం సాధ్యం కాలేదు", + "kdsLoadHint": "మీ లోకల్ నెట్వర్క్లో కిచెన్ డిస్ప్లే పరికరాలను జత చేయడానికి కనెక్షన్ వివరాలను లోడ్ చేయండి.", + "kdsPairing": "కిచెన్ డిస్ప్లే (KDS) జత చేయడం", + "kdsPairingHiddenHint": "కిచెన్ డిస్ప్లే సిస్టమ్ నిలిపివేయబడినప్పుడు జత చేయడం దాచబడుతుంది.", + "kdsPairingHint": "అదే WiFi లో ఉన్న ఏదైనా టాబ్లెట్ లేదా మానిటర్లో బ్రౌజర్ తెరిచి, దాన్ని కిచెన్ డిస్ప్లేగా కనెక్ట్ చేయడానికి QR కోడ్ను స్కాన్ చేయండి (లేదా URL టైప్ చేయండి).", + "kdsQrAlt": "KDS QR కోడ్", + "kdsViewSaveFailed": "డిఫాల్ట్ వ్యూను సేవ్ చేయడం సాధ్యం కాలేదు", + "kdsViewSaved": "డిఫాల్ట్ వ్యూ సేవ్ చేయబడింది", + "kitchenStations": "కిచెన్ స్టేషన్లు", + "kitchenStationsHint": "కేటగిరీలను కిచెన్ స్టేషన్కు రూట్ చేయండి, దాని ప్రింటర్ను ఎంచుకోండి మరియు KDS లో ఆ ఐటెమ్లను చూడాల్సిన చెఫ్ను కేటాయించండి.", + "kitchenWorkflowBothOffNote": "కిచెన్ డిస్ప్లే మరియు KOT ప్రింటింగ్ రెండూ ఆఫ్లో ఉన్నాయి. కిచెన్ ఐటెమ్లు ఎక్కడా కనిపించవు లేదా ప్రింట్ కావు — ఆర్డర్లను నేరుగా కౌంటర్ వద్దే వడ్డించినట్లు మార్క్ చేయాల్సి ఉంటుంది.", + "kotPrintLanguage": "కిచెన్ టికెట్ భాష", + "kotPrintLanguageHint": "నిర్దిష్ట భాషను ఎంచుకోకపోతే కిచెన్ టికెట్లు స్టోర్ భాషను అనుసరిస్తాయి.", + "kotPrintingEnabledOff": "KOT ప్రింటింగ్ నిలిపివేయబడింది", + "kotPrintingEnabledOn": "KOT ప్రింటింగ్ ప్రారంభించబడింది", + "kotPrintingEnabledToggle": "KOT టికెట్ ప్రింటింగ్", + "kotPrintingEnabledToggleHint": "KOT టికెట్లు ఆటోమేటిక్గా లేదా మాన్యువల్గా ప్రింట్ అవ్వడానికి అనుమతించండి. ఈ వ్యాపారం KOT ప్రింటర్ ఉపయోగించకపోతే దీన్ని ఆఫ్ చేయండి.", + "languageEn": "English (EN)", + "languageEs": "Español (ES)", + "languageFa": "పర్షియన్ (FA)", + "languagePt": "Português (PT)", + "languages": "భాషలు", + "lastActive": "చివరిగా యాక్టివ్గా ఉన్నది {date}", + "lastSync": "చివరి సింక్: {time}", + "liveChannel": "లైవ్ ఛానెల్: {mode}", + "liveChannelHeartbeat": "లైవ్ ఛానెల్: {mode} · చివరి హార్ట్బీట్ {time}", + "loadFailed": "చెల్లింపు సెట్టింగ్లను లోడ్ చేయడం సాధ్యం కాలేదు", + "loadKdsInfo": "KDS సమాచారాన్ని లోడ్ చేయండి", + "loadPosInfo": "POS సమాచారాన్ని లోడ్ చేయండి", + "loadServerAppInfo": "సర్వర్ యాప్ సమాచారాన్ని లోడ్ చేయండి", + "loading": "లోడ్ అవుతోంది…", + "localNetwork": "లోకల్ నెట్వర్క్", + "localNetworkHint": "అన్ని పరికరాలు Wi-Fi, Ethernet లేదా VPN/మెష్ నెట్వర్క్ ద్వారా ఈ చిరునామాను చేరుకోగలిగినప్పుడు ఉపయోగించండి", + "loyalty": "లాయల్టీ", + "loyaltyHint": "కార్ట్లోని ప్రతి ఐటెమ్ యొక్క లాయల్టీ సంపాదన రేటు ఆధారంగా కస్టమర్లు పాయింట్లు సంపాదిస్తారు", + "loyaltyProgram": "లాయల్టీ ప్రోగ్రామ్", + "loyaltySaved": "లాయల్టీ సెట్టింగ్లు సేవ్ చేయబడ్డాయి", + "masterPin": "మాస్టర్ PIN", + "masterPinChangeButton": "PIN మార్చండి", + "masterPinDataDescription": "ఈ డేటాబేస్ను బ్యాకప్ చేయడానికి, పునరుద్ధరించడానికి లేదా ప్రారంభించడానికి అవసరమైన 4-అంకెల PIN (ఏ సిబ్బంది లాగిన్తో సంబంధం లేనిది). డేటాబేస్తో సంబంధం లేకుండా ఈ పరికరంలో ఎన్క్రిప్ట్ చేయబడి నిల్వ చేయబడుతుంది — కాబట్టి డేటాబేస్ పాడైపోయినా లేదా లాక్ చేయబడినా మీరు దీన్ని ఉపయోగించవచ్చు.", + "masterPinRequiredForBackup": "బ్యాకప్ సృష్టించే ముందు క్రింద మాస్టర్ PIN సెట్ చేయండి", + "masterPinRequiredForReplace": "డేటా మొత్తాన్ని భర్తీ చేసే ముందు క్రింద మాస్టర్ PIN సెట్ చేయండి", + "masterPinSaved": "మాస్టర్ PIN సేవ్ చేయబడింది", + "masterPinSetButton": "PIN సెట్ చేయండి", + "masterPinStatusNotSet": "సెట్ చేయలేదు", + "masterPinStatusSet": "PIN సెట్ చేయబడింది", + "maxDiscountAmount": "గరిష్ట తగ్గింపు మొత్తం", + "maxDiscountAmountHint": "తగ్గింపుల కోసం గరిష్ట స్థిర మొత్తం", + "maxDiscountPercentage": "గరిష్ట తగ్గింపు శాతం", + "maxDiscountPercentageHint": "శాతం తగ్గింపుల కోసం గరిష్ట శాతం", + "mdnsAlwaysStable": "mDNS (ఎల్లప్పుడూ స్థిరమైనది)", + "merge": "విలీనం చేయి", + "mergeHistory": "చరిత్రను విలీనం చేయి", + "mergeInto": "దీనిలోకి విలీనం చేయి", + "mergePaymentMethodConfirm": "ఈ పద్ధతిని మరియు దీని గత చెల్లింపులన్నింటినీ ఎంచుకున్న పద్ధతిలోకి విలీనం చేయాలా? దీన్ని రద్దు చేయలేరు.", + "mobileApp": "యాప్ కోడ్", + "mobileAppHint": "మీ ఖాతాతో జత చేయడానికి RevFlo యాప్లో ఈ కోడ్ను నమోదు చేయండి.", + "mobilePairingNeedsCloud": "ముందుగా పైన క్లౌడ్ సేవలను ప్రారంభించండి — జత చేసే కోడ్లు FloAdmin ద్వారా జారీ చేయబడతాయి.", + "moreApps": "మరిన్ని యాప్లు", + "moreAppsHint": "Flo POS కుటుంబానికి అనుబంధ యాప్లు. డౌన్లోడ్ చేయడానికి మీ ఫోన్తో QR కోడ్ను స్కాన్ చేయండి.", + "name": "పేరు", + "navGroupAccount": "ఖాతా", + "navGroupCustomers": "కస్టమర్లు", + "navGroupData": "ఇంటిగ్రేషన్లు", + "navGroupGeneral": "సాధారణ", + "navGroupOperations": "కార్యకలాపాలు", + "newPin": "కొత్త PIN", + "no": "కాదు", + "noAccessDatabase": "బ్యాకప్ మరియు డేటాబేస్ టూల్స్కు మీకు యాక్సెస్ లేదు.", + "noAccessMobileAccess": "మొబైల్ యాక్సెస్ సెట్టింగ్లకు మీకు యాక్సెస్ లేదు.", + "noAppsToShow": "చూపించడానికి ఇంకా యాప్లు లేవు.", + "noCategoriesYet": "ఇంకా కేటగిరీలు లేవు. ముందుగా ఉత్పత్తుల క్రింద కేటగిరీలను జోడించండి.", + "noChefsYet": "ఇంకా యాక్టివ్ చెఫ్ ఖాతాలు లేవు. ముందుగా సిబ్బంది క్రింద ఒక చెఫ్ను జోడించండి.", + "noCloudContactEmail": "క్లౌడ్ సంప్రదింపు ఇమెయిల్ లేదు", + "noInstalledPrinters": "ఇన్స్టాల్ చేయబడిన ప్రింటర్లు ఏవీ కనుగొనబడలేదు. సిస్టమ్ సెట్టింగ్ల ద్వారా మీ ప్రింటర్ను ఇన్స్టాల్ చేసి, రిఫ్రెష్ క్లిక్ చేయండి — లేదా నెట్వర్క్ ప్రింటర్ కోసం మాన్యువల్గా జోడించండి ఉపయోగించండి.", + "noPairedDevices": "ఇంకా ఏ పరికరాలు జత చేయబడలేదు.", + "noPrintersConfigured": "ఇంకా ప్రింటర్లు కాన్ఫిగర్ చేయబడలేదు.", + "noStaffYet": "ఇంకా సిబ్బంది లాగిన్లు లేవు.", + "noStationsYet": "ఇంకా కిచెన్ స్టేషన్లు లేవు — ప్రతి టికెట్ డిఫాల్ట్ ప్రింటర్లోనే ప్రింట్ అవుతుంది.", + "notAvailableOnDevice": "ఈ పరికరంలో అందుబాటులో లేదు.", + "notRegistered": "నమోదు కాలేదు", + "nothingPending": "పెండింగ్లో ఏమీ లేదు", + "optional": "(ఐచ్ఛికం)", + "orderNumberFormat": "నంబర్ ఫార్మాట్లు", + "orderNumberIncludeDate": "ఆర్డర్ నంబర్లో తేదీని చేర్చండి", + "orderNumberIncludeDateHint": "ప్రిఫిక్స్ తర్వాత ప్రస్తుత తేదీని (YYYYMMDD) జోడిస్తుంది.", + "orderNumberPrefix": "ప్రిఫిక్స్", + "orderNumberPrefixInvalid": "ప్రిఫిక్స్ గరిష్టంగా 12 అక్షరాలు మరియు అంకెలు మాత్రమే ఉండాలి", + "orderNumberPreview": "ప్రివ్యూ", + "orderNumberResetDaily": "ప్రతి 24 గంటలకు సిరీస్ రీసెట్ చేయండి", + "orderNumberResetDailyHint": "స్టోర్ టైమ్జోన్లో అర్ధరాత్రి నుండి నంబరింగ్ 1 నుండి మళ్లీ మొదలవుతుంది.", + "orderNumberingSaved": "నంబరింగ్ సెట్టింగ్లు సేవ్ చేయబడ్డాయి", + "orderNumbers": "ఆర్డర్ నంబర్లు", + "orderflowOnlineOrders": "OrderFlow — ఆన్లైన్ ఆర్డర్లు", + "orderflowOnlineOrdersHint": "Zomato, Swiggy మరియు ఇతర ప్లాట్ఫారమ్ల నుండి నేరుగా ఈ POS లో ఆర్డర్లను స్వీకరించండి", + "pairedDevices": "జత చేయబడిన పరికరాలు", + "pairingCodeFailed": "కోడ్ రూపొందించడం విఫలమైంది", + "pairingCodeRotated": "కొత్త జత చేసే కోడ్ రూపొందించబడింది", + "pairingCodeSingleUse": "ఈ కోడ్ ఒక RevFlo పరికరాన్ని మాత్రమే జత చేయగలదు. మరో పరికరం కోసం కొత్త కోడ్ రూపొందించండి.", + "pairingQrAlt": "RevFlo జత చేసే QR కోడ్", + "paperSize": "పేపర్ పరిమాణం", + "paperSize58": "2.5\" (58mm)", + "paperSize80": "3.5\" (80mm)", + "paperWidth": "ప్రింట్ చేయగల నిలువు వరుసలు", + "paperWidth58": "2.5\" (58mm, 32 వరుసలు)", + "paperWidth58Wide": "సన్నని రోల్ (36 వరుసలు)", + "paperWidth80": "3.5\" (80mm, 48 వరుసలు - వెడల్పు)", + "paperWidth80Safe": "3.5\" (80mm, 42 వరుసలు - సురక్షితం)", + "paymentMethodMerged": "చెల్లింపు పద్ధతులు విలీనం చేయబడ్డాయి", + "paymentMethodName": "చెల్లింపు పద్ధతి పేరు", + "paymentMethods": "చెల్లింపులు", + "paymentMethodsHint": "నగదు, కార్డు మరియు లాయల్టీ వాలెట్ ఎల్లప్పుడూ అందుబాటులో ఉంటాయి. మీ రెస్టారెంట్ ఉపయోగించే ఇతర మాన్యువల్ చెల్లింపు పేర్లను జోడించండి.", + "percentDownloaded": "{percent}% డౌన్లోడ్ చేయబడింది", + "percentMaximum": "గరిష్టంగా 100%", + "percentZeroNoLimit": "% (0 = పరిమితి లేదు)", + "phone": "ఫోన్", + "phoneDigits": "ఫోన్ నంబర్ అంకెలు", + "phoneDigitsDerived": "పైన ఎంచుకున్న దేశం ఆధారంగా ఫోన్ అంకెల సంఖ్య ఆటోమేటిక్గా నిర్ణయించబడుతుంది.", + "phoneDigitsHint": "ఫోన్ ధృవీకరణ కోసం అవసరమైన అంకెల సంఖ్య (ఉదా. {country} కోసం {count})", + "phoneNumberDigits": "ఫోన్ నంబర్ అంకెలు", + "phonePlaceholder": "{dialCode} ఫోన్ నంబర్", + "pinFourDigits": "PIN ఖచ్చితంగా 4 అంకెలు ఉండాలి", + "pinMismatch": "PINలు సరిపోలడం లేదు", + "plan": "ప్లాన్", + "port": "పోర్ట్", + "portPlaceholder": "9100", + "posDisplay": "POS ప్రదర్శన", + "posInfoFetchFailed": "POS సమాచారాన్ని పొందడం సాధ్యం కాలేదు", + "posLoadHint": "మీ లోకల్ నెట్వర్క్లో మరో బిల్లింగ్ టెర్మినల్ను జత చేయడానికి కనెక్షన్ వివరాలను లోడ్ చేయండి.", + "posPairing": "బిల్లింగ్ టెర్మినల్ జోడించండి", + "posPairingHint": "అదే WiFi లో ఉన్న ఏదైనా పరికరంలో బ్రౌజర్ తెరిచి, ఈ POS ను మరో బిల్లింగ్ టెర్మినల్గా తెరవడానికి QR కోడ్ను స్కాన్ చేయండి (లేదా URL టైప్ చేయండి).", + "posQrAlt": "POS QR కోడ్", + "posSettings": "POS సెట్టింగ్లు", + "posWorkflow": "POS వర్క్ఫ్లో", + "printBillOnPayment": "చెల్లింపు పూర్తయినప్పుడు బిల్ ప్రింట్ చేయండి", + "printColumns32": "32 నిలువు వరుసలు - అత్యంత సురక్షితమైన 58mm", + "printColumns36": "36 నిలువు వరుసలు - నారో డ్రైవర్", + "printColumns40": "40 నిలువు వరుసలు", + "printColumns42": "42 నిలువు వరుసలు - సాధారణ 80mm సురక్షితం", + "printColumns44": "44 నిలువు వరుసలు", + "printColumns48": "48 నిలువు వరుసలు - వెడల్పు 80mm", + "printerTextSize": "టెక్స్ట్ పరిమాణం", + "printerTextSizeNormal": "సాధారణం", + "printerTextSizeLarge": "పెద్దది", + "printerTextSizeExtraLarge": "చాలా పెద్దది", + "printColumnsShort": "{cols} నిలువు వరుసలు", + "printKotOnPlace": "ఆర్డర్ వేసినప్పుడు KOT ప్రింట్ చేయండి", + "printMethod": "ప్రింట్ పద్ధతి", + "printMethodBrowser": "బ్రౌజర్ ప్రింట్ (ఏదైనా ప్రింటర్)", + "printMethodBrowserHint": "బ్రౌజర్ ప్రింట్ డైలాగ్ను తెరుస్తుంది — ఈ కంప్యూటర్లోని ఏ ప్రింటర్తోనైనా పనిచేస్తుంది", + "printMethodEscpos": "ESCPOS (USB / నెట్వర్క్ థర్మల్ ప్రింటర్)", + "printMethodEscposHint": "USB, నెట్వర్క్ మరియు WebUSB ప్రింటర్ల కోసం నేరుగా థర్మల్ ప్రింటింగ్ — రసీదు ప్రింటర్ల కోసం దీన్ని ఎంచుకుని ఉంచండి", + "printerAddFailed": "ప్రింటర్ జోడించడం విఫలమైంది", + "printerAdded": "జోడించబడింది", + "printerAdding": "జోడిస్తోంది…", + "printerArabicShaping": "ప్రింటర్ అరబిక్/పర్షియన్ షేపింగ్కు మద్దతు ఇస్తుంది", + "printerArabicShapingHint": "ఆన్లో ఉంటే, పర్షియన్/అరబిక్ టెక్స్ట్ ఉన్న రసీదు లైన్లు యథాతథంగా ప్రింటర్కు పంపబడతాయి — మీ ప్రింటర్ పర్షియన్ను సరిగ్గా ప్రింట్ చేస్తేనే దీన్ని ప్రారంభించండి. ఆఫ్లో ఉంటే, ఆ లైన్లు దాటవేయబడతాయి.", + "printerDeleteConfirm": "ఈ ప్రింటర్ను తొలగించాలా?", + "printerDeleteFailed": "తొలగించడం విఫలమైంది", + "printerDeleted": "ప్రింటర్ తొలగించబడింది", + "printerHint": "ఇన్స్టాల్ చేయబడిన ప్రింటర్పై జోడించు క్లిక్ చేయండి, లేదా మాన్యువల్గా జోడించండి ఉపయోగించండి.", + "printerName": "ప్రింటర్ పేరు *", + "printerNameMismatchWarning": "ఈ పేరు కనుగొనబడిన ఏ ప్రింటర్తోనూ సరిపోలడం లేదు. ఇది ఈ కంప్యూటర్లోని ప్రింటర్ పేరుతో ఖచ్చితంగా సరిపోలాలి, లేకపోతే టెస్ట్ ప్రింట్ విఫలమవుతుంది.", + "printerNamePlaceholder": "ఉదా. కిచెన్ ప్రింటర్", + "printerNameRequired": "ప్రింటర్ పేరు అవసరం", + "printerOffline": "ఆఫ్లైన్", + "printerConfigured": "ప్రింటర్ కాన్ఫిగర్ చేయబడింది", + "printerOnline": "ఆన్లైన్", + "printerPrinting": "ప్రింట్ అవుతోంది", + "printerQuickAdded": "{name} జోడించబడింది", + "printerSaveFailed": "ప్రింటర్ సేవ్ చేయడం విఫలమైంది", + "printerSaved": "ప్రింటర్ జోడించబడింది", + "printerSupportedProfile": "మద్దతు ఉన్న ప్రొఫైల్", + "printerUnicode": "ప్రింటర్ యూనికోడ్కు మద్దతు ఇస్తుంది", + "printerUnicodeHint": "ఆన్లో ఉంటే, కరెన్సీ చిహ్నాలను (₹, €, £, ¥…) యథాతథంగా ప్రింట్ చేస్తుంది. ఆఫ్లో ఉంటే, వాటిని ASCII (Rs, EUR, GBP, Yen…) తో భర్తీ చేస్తుంది — చాలా థర్మల్ ప్రింటర్లకు ఇది సురక్షితమైన డిఫాల్ట్.", + "printerUpdated": "ప్రింటర్ అప్డేట్ చేయబడింది", + "printers": "ప్రింటర్లు", + "printingSettingsSaved": "ప్రింటింగ్ సెట్టింగ్లు సేవ్ చేయబడ్డాయి", + "privacy": "గోప్యత", + "productImagesDisabled": "ఉత్పత్తి చిత్రాలు నిలిపివేయబడ్డాయి", + "productImagesEnabled": "ఉత్పత్తి చిత్రాలు ప్రారంభించబడ్డాయి", + "receiptLanguage": "రసీదు భాష", + "receiptLanguageHint": "రసీదుల కోసం స్టోర్ భాషను ఎంచుకోండి లేదా నిర్దిష్ట భాషను స్థిరపరచండి.", + "refresh": "రిఫ్రెష్", + "refreshList": "ఇన్స్టాల్ చేయబడిన ప్రింటర్ల జాబితాను రిఫ్రెష్ చేయండి", + "refreshUrls": "URLలను రిఫ్రెష్ చేయండి", + "registerWithFloadmin": "FloAdmin తో నమోదు చేయండి", + "registeredReconnecting": "నమోదు చేయబడింది (మళ్లీ కనెక్ట్ అవుతోంది…)", + "registering": "నమోదు అవుతోంది…", + "registrationContactSupport": "సపోర్ట్ను సంప్రదించండి — ఈ ఇన్స్టాల్ ఆమోదించబడలేదు", + "registrationEmailPlaceholder": "owner@yourcafe.com", + "registrationLastError": "{error}", + "registrationLastFailed": "చివరి ప్రయత్నం విఫలమైంది — ఆటోమేటిక్గా మళ్లీ ప్రయత్నిస్తూనే ఉంటుంది", + "registrationRegisterHelp": "ఈ POS ను FloAdmin కు తెలియజేయడానికి నమోదు చేయండి, లేదా క్రింద API కీని పేస్ట్ చేయండి", + "registrationRejected": "రిజిస్ట్రేషన్ తిరస్కరించబడింది", + "reloadFailed": "సెట్టింగ్లను రీలోడ్ చేయడం విఫలమైంది", + "reloadedFromDb": "డేటాబేస్ నుండి సెట్టింగ్లు రీలోడ్ చేయబడ్డాయి", + "replaceAll": "అన్నీ భర్తీ చేయండి", + "requireApproval": "ఆమోదం అవసరం", + "requireApprovalHint": "తగ్గింపులను వర్తింపజేయడానికి మేనేజర్ PIN అవసరం", + "restoreBackup": "పునరుద్ధరించు", + "restoreConfirm": "{fileName} నుండి పునరుద్ధరించాలా? ఇది ప్రస్తుత డేటా మొత్తాన్ని భర్తీ చేస్తుంది.", + "restoreFailedGeneric": "పునరుద్ధరణ విఫలమైంది", + "retry": "మళ్లీ ప్రయత్నించు", + "revflo": "RevFlo", + "revfloHint": "మీ ఫోన్ నుండే మీ స్టోర్ యొక్క లైవ్ అమ్మకాలు, రోజువారీ సారాంశాలు మరియు నివేదికలను చూడండి.", + "role": "పాత్ర", + "rowCountsForAll": "అన్ని టేబుళ్ల వరుసల సంఖ్య", + "rows": "వరుసలు", + "sameAsStore": "స్టోర్ భాషే", + "save": "సేవ్ చేయి", + "saveAll": "అన్నీ సేవ్ చేయి", + "saveChanges": "మార్పులను సేవ్ చేయి", + "saveCloudSettings": "క్లౌడ్ సెట్టింగ్లను సేవ్ చేయి", + "saveFailed": "సేవ్ చేయడం విఫలమైంది", + "savePinFailed": "PIN సేవ్ చేయడం విఫలమైంది", + "saving": "సేవ్ అవుతోంది...", + "savingCloud": "సేవ్ అవుతోంది…", + "scanningForPrinters": "ఇన్స్టాల్ చేయబడిన ప్రింటర్ల కోసం స్కాన్ చేస్తోంది…", + "secondLanguageNone": "ఏదీ లేదు", + "secondReceiptLanguage": "రెండవ రసీదు భాష", + "zReportLanguage": "Z-నివేదిక భాష", + "secondZReportLanguage": "రెండవ Z-నివేదిక భాష", + "zReportLanguageHint": "నిర్దిష్ట భాషను ఎంచుకోకపోతే Z నివేదికలు స్టోర్ భాషను అనుసరిస్తాయి.", + "selectCountry": "దేశాన్ని ఎంచుకోండి...", + "selectFileAndImport": "ఫైల్ ఎంచుకుని దిగుమతి చేయండి", + "selectTimezone": "టైమ్జోన్ ఎంచుకోండి…", + "serverApp": "సర్వర్ యాప్", + "serverAppBillPrinting": "సర్వర్ బిల్ ప్రింటింగ్", + "serverAppBillPrintingEnabledOff": "సర్వర్ బిల్ ప్రింటింగ్ నిలిపివేయబడింది", + "serverAppBillPrintingEnabledOn": "సర్వర్ బిల్ ప్రింటింగ్ ప్రారంభించబడింది", + "serverAppBillPrintingHint": "సర్వీస్ సిబ్బంది టేబుల్సైడ్ టెర్మినల్ నుండి కిచెన్ టికెట్ మాత్రమే కాకుండా కస్టమర్ బిల్/ఆర్డర్-స్లిప్ కూడా ప్రింట్ చేయడానికి అనుమతించండి.", + "serverAppEnabledHint": "టేబుల్సైడ్ ఆర్డరింగ్ కోసం సర్వీస్ సిబ్బంది మొబైల్/టాబ్లెట్-అనుకూల ఆర్డర్ ప్యాడ్ను తెరవడానికి అనుమతించండి.", + "serverAppEnabledOff": "సర్వర్ యాప్ నిలిపివేయబడింది", + "serverAppEnabledOn": "సర్వర్ యాప్ ప్రారంభించబడింది", + "serverAppInfoFetchFailed": "సర్వర్ యాప్ సమాచారాన్ని లోడ్ చేయడం సాధ్యం కాలేదు", + "serverAppLoadHint": "మీ లోకల్ నెట్వర్క్లో టేబుల్సైడ్ ఆర్డరింగ్ పరికరాలను జత చేయడానికి కనెక్షన్ వివరాలను లోడ్ చేయండి.", + "serverAppPairingHiddenHint": "సర్వర్ యాప్ నిలిపివేయబడినప్పుడు జత చేయడం దాచబడుతుంది.", + "serverAppPairingHint": "మీ లోకల్ నెట్వర్క్లో సర్వర్ల ఫోన్లు లేదా టాబ్లెట్లను జత చేయండి. వారు టేబుల్ ఆర్డర్లు నమోదు చేయగలరు మరియు కిచెన్ స్థితి చిహ్నాలను చూడగలరు.", + "serverAppQrAlt": "సర్వర్ యాప్ QR కోడ్", + "setAsDefault": "డిఫాల్ట్గా సెట్ చేయండి", + "setMasterPinFirst": "ఈ చర్య చేసే ముందు సెట్టింగ్లు → డేటా లో మాస్టర్ PIN సెట్ చేయండి", + "setPinButton": "PIN సెట్ చేయండి", + "setPinDescription": "మీకు మాత్రమే తెలిసిన 4-అంకెల PIN ఎంచుకోండి. బ్యాకప్లు, పునరుద్ధరణలు మరియు డేటాబేస్ ప్రారంభించడానికి ఇది అవసరం.", + "showCustomerName": "కస్టమర్ పేరు", + "showCustomerPhone": "కస్టమర్ నంబర్", + "showProductImages": "ఉత్పత్తి చిత్రాలను చూపించు", + "showProductImagesHint": "POS గ్రిడ్లో ఉత్పత్తి చిత్రాలను ప్రదర్శించండి", + "showRestaurantAddress": "రెస్టారెంట్ చిరునామా", + "showRestaurantName": "రెస్టారెంట్ పేరు", + "showRestaurantPhone": "రెస్టారెంట్ ఫోన్", + "showTableNumber": "టేబుల్ నంబర్", + "showTaxBreakdown": "పన్ను వివరాలు", + "showTaxId": "పన్ను ID నంబర్", + "softwareUpdates": "సాఫ్ట్వేర్ అప్డేట్లు", + "softwareUpdatesHintDefault": "మీరు క్రింద ఆఫ్ చేయకపోతే Flo Cafe ప్రారంభమైనప్పుడు అప్డేట్ల కోసం తనిఖీ చేస్తుంది మరియు డౌన్లోడ్ చేసే ముందు ఎల్లప్పుడూ అడుగుతుంది. మీరు మాన్యువల్గా కూడా తనిఖీ చేయవచ్చు.", + "softwareUpdatesHintBrowser": "అప్డేట్లు FloCafe డెస్క్టాప్ యాప్ ద్వారా నిర్వహించబడతాయి.", + "softwareUpdatesHintLinuxManaged": "ఈ ఇన్స్టాల్ Flo యొక్క ఇన్-యాప్ అప్డేటర్ ద్వారా కాకుండా మీ Linux ప్యాకేజ్ మేనేజర్ (deb/rpm) లేదా Snap Store ద్వారా నిర్వహించబడుతుంది. AppImage బిల్డ్లు ఆటోమేటిక్గా అప్డేట్ అవుతాయి.", + "softwareUpdatesHintStore": "ఈ వెర్షన్ App Store ద్వారా పంపిణీ చేయబడింది. అప్డేట్లు స్టోర్ ద్వారా నిర్వహించబడతాయి.", + "splitChecks": "బిల్లుల విభజన", + "splitChecksHint": "డైన్-ఇన్ ఐటెమ్లను లేదా పరిమాణాలను వేర్వేరు బిల్లులుగా విభజించడానికి అనుమతించండి. డిఫాల్ట్గా నిలిపివేయబడి ఉంటుంది.", + "cardTransactionIdRequired": "కార్డు లావాదేవీ నంబర్ తప్పనిసరి", + "cardTransactionIdRequiredHint": "నివేదికలను కార్డు టెర్మినల్తో సరిపోల్చడానికి, కార్డు చెల్లింపుల్లో టెర్మినల్ జారీ చేసిన లావాదేవీ నంబర్ తప్పనిసరిగా ఉండాలి. డిఫాల్ట్గా నిలిపివేయబడి ఉంటుంది.", + "stationAssignedCategories": "మరొక చోట కేటాయించబడింది — తరలించడానికి ఎంచుకోండి", + "stationAvailableCategories": "అందుబాటులో ఉన్న కేటగిరీలు", + "stationCategories": "ఇక్కడికి రూట్ చేయబడిన కేటగిరీలు", + "stationChef": "కేటాయించబడిన చెఫ్లు", + "stationChefRequiresKds": "ఈ స్టేషన్కు చెఫ్ను కేటాయించడానికి KDS ను ప్రారంభించండి.", + "stationDeleteConfirm": "ఈ కిచెన్ స్టేషన్ను తొలగించాలా? దీనికి రూట్ చేయబడిన ఐటెమ్లు డిఫాల్ట్ ప్రింటర్కు మారుతాయి.", + "stationDeleteFailed": "స్టేషన్ను తొలగించడం సాధ్యం కాలేదు", + "stationDeleted": "స్టేషన్ తొలగించబడింది", + "stationFormHint": "ఇక్కడ నిర్వహించే కేటగిరీలు, వాటి టికెట్ల కోసం ప్రింటర్ మరియు KDS లో వాటిని చూడాల్సిన చెఫ్ను ఎంచుకోండి.", + "stationName": "స్టేషన్ పేరు", + "stationNamePlaceholder": "ఉదా. బార్, డెజర్ట్ కౌంటర్", + "stationNameRequired": "స్టేషన్ పేరు అవసరం", + "stationNoAvailableCategories": "అందుబాటులో కేటగిరీలు లేవు", + "stationNoCategories": "కేటగిరీలు కేటాయించబడలేదు", + "stationNoChef": "చెఫ్ కేటాయించబడలేదు", + "stationNoDefaultCategories": "అన్ని కేటగిరీలు కిచెన్ స్టేషన్లకు కేటాయించబడ్డాయి", + "stationNoPrinter": "డిఫాల్ట్ ప్రింటర్", + "stationNoPrinterConfigured": "ప్రింటర్ కాన్ఫిగర్ చేయబడలేదు", + "stationPrinter": "ప్రింటర్", + "stationSaveFailed": "స్టేషన్ను సేవ్ చేయడం సాధ్యం కాలేదు", + "stationSaved": "స్టేషన్ సృష్టించబడింది", + "stationSelectedCategories": "ఈ స్టేషన్ కోసం ఎంచుకోబడినవి", + "stationStaff": "కేటాయించబడిన సిబ్బంది", + "stationUpdated": "స్టేషన్ అప్డేట్ చేయబడింది", + "stationUseDefaultPrinter": "డిఫాల్ట్ ప్రింటర్ను ఉపయోగించండి", + "status": "స్థితి", + "storeDetails": "స్టోర్ వివరాలు", + "storeDiagnostics": "స్టోర్ డయాగ్నస్టిక్స్ (సపోర్ట్ కోసం)", + "storeDiagnosticsHint": "స్టోర్తో అనుబంధించబడిన నిర్దిష్ట సమస్య నివేదికలను అనుమతిస్తుంది. ఈ పరికరం నుండి నివేదికలు బయటకు వెళ్లాలంటే ఈ అనుమతి మరియు ఆటోమేటిక్గా డయాగ్నస్టిక్స్ పంపడం రెండూ ఆన్లో ఉండాలి. రెండింటిలో ఏ ఒక్కటి ఆఫ్ చేసినా పరిమిత లోకల్ ఆధారాలు పరికరంలోనే ఉండి పంపడం ఆగిపోతుంది. నివేదికలలో కస్టమర్ పేర్లు, ఫోన్ నంబర్లు, చిరునామాలు, ఆర్డర్ వివరాలు మరియు చెల్లింపు వివరాలు ఉండవు. ఇది అజ్ఞాత వినియోగ టెలిమెట్రీ నుండి వేరుగా ఉంటుంది.", + "storeId": "స్టోర్ ID", + "storeIdPending": "స్టోర్ ID {id} — FloAdmin బృంద సభ్యుడు ఈ ఇన్స్టాల్ను క్లెయిమ్ చేయాలి", + "storeIdPlaceholder": "మొదటి సింక్ తర్వాత ఆటోమేటిక్గా నింపబడుతుంది", + "storeSaved": "స్టోర్ వివరాలు సేవ్ చేయబడ్డాయి", + "subscription": "సబ్స్క్రిప్షన్", + "tabAbout": "గురించి", + "tabBackupData": "బ్యాకప్ & డేటా", + "tabBillTemplate": "బిల్ టెంప్లేట్", + "tabCloud": "క్లౌడ్ సింక్", + "tabData": "డేటా", + "tabDataCloud": "డేటా & క్లౌడ్", + "tabGeneral": "సాధారణ", + "tabKds": "కిచెన్ డిస్ప్లే", + "tabQrMenu": "QR మెనూ", + "tabMobileAccess": "మొబైల్ యాక్సెస్", + "tabMoreApps": "మరిన్ని యాప్లు", + "tabOrderflow": "OrderFlow", + "tabPrinters": "ప్రింటర్లు", + "tabPrinting": "ప్రింట్ ఎంపికలు", + "tabReceiptsPrinters": "రసీదులు & ప్రింటర్లు", + "tabUpdates": "సాఫ్ట్వేర్ అప్డేట్లు", + "tabWhatsapp": "WhatsApp", + "tableInfoFailed": "టేబుల్ సమాచారాన్ని పొందడం విఫలమైంది", + "tablesRequired": "టేబుళ్లు తప్పనిసరి", + "tablesRequiredNo": "కాదు – టేబుల్ ఎంపిక ఐచ్ఛికం", + "tablesRequiredYes": "అవును – డైన్-ఇన్ కోసం టేబుల్ తప్పనిసరి", + "tablesideOrdering": "టేబుల్సైడ్ ఆర్డరింగ్", + "taxConfiguration": "పన్ను కాన్ఫిగరేషన్", + "taxIdFormatWarning": "ఆశించిన {country} పన్ను ID ఫార్మాట్తో సరిపోలడం లేదు: {format}", + "taxIdLabel": "పన్ను ID", + "taxIdPlaceholder": "పన్ను ID నమోదు చేయండి", + "taxRegistered": "పన్ను నమోదు చేయబడింది", + "taxSupportUnavailable": "{country} కోసం పన్ను మద్దతు ఇంకా అందుబాటులో లేదు. మేము ప్లగిన్ను అభ్యర్థించాము మరియు త్వరలో దాన్ని నిర్మిస్తాము. ప్రస్తుతానికి పన్నులు ఆఫ్ చేయబడ్డాయి.", + "test": "పరీక్ష", + "testPrint": "టెస్ట్ ప్రింట్", + "testPrintFailed": "టెస్ట్ ప్రింట్ విఫలమైంది", + "testPrintSent": "టెస్ట్ ప్రింట్ పంపబడింది!", + "cashDrawerPulseSent": "క్యాష్ డ్రాయర్ పల్స్ పంపబడింది.", + "cashDrawerPulseFailed": "క్యాష్ డ్రాయర్ పల్స్ పంపడం విఫలమైంది.", + "testing": "పరీక్షిస్తోంది…", + "timezone": "టైమ్జోన్", + "businessDayStartTime": "వ్యాపార దినం ప్రారంభ సమయం", + "businessDayStartTimeDesc": "అర్ధరాత్రి దాటి నడిచే వ్యాపారాల కోసం, అర్ధరాత్రి తర్వాత ఈ సమయం వరకు జరిగే అమ్మకాలు మునుపటి రోజు అమ్మకాలు మరియు దిన ముగింపులో లెక్కించబడతాయి.", + "defaultMidnight": "డిఫాల్ట్ - అర్ధరాత్రి", + "title": "సెట్టింగ్లు", + "trimDecimals": "దశాంశాలను కుదించు", + "trimDecimalsHint": "ప్రింట్ చేసిన రసీదులపై చివర వచ్చే .00 ను దాచండి. సెంట్లు/పైసలు ఉన్న విలువలు దశాంశాలతోనే ప్రింట్ అవుతాయి.", + "unicode": "యూనికోడ్", + "unknownPlatform": "తెలియని పరికరం", + "unsavedChanges": "మీ వద్ద సేవ్ చేయని మార్పులు ఉన్నాయి", + "unsavedChangesPrompt": "మీ వద్ద సేవ్ చేయని మార్పులు ఉన్నాయి. మీరు ఖచ్చితంగా నిష్క్రమించాలనుకుంటున్నారా?", + "upToDate": "మీరు సరికొత్త వెర్షన్ ఉపయోగిస్తున్నారు!", + "updateLatestAvailable": "అందుబాటులో ఉన్న సరికొత్తది:", + "updateStatusAvailable": "అందుబాటులో ఉంది", + "updateStatusReadyToInstall": "ఇన్స్టాల్ చేయడానికి సిద్ధంగా ఉంది", + "updateStatusUpToDate": "తాజాగా ఉంది", + "updateStatusNotCheckedYet": "ఇంకా తనిఖీ చేయలేదు", + "updateStatusDownloading": "అప్డేట్ డౌన్లోడ్ అవుతోంది...", + "updateStatusCheckFailed": "అప్డేట్ తనిఖీ విఫలమైంది", + "updateStatusOffline": "ఆఫ్లైన్", + "updateStatusOfflineHint": "మీరు ఆఫ్లైన్లో ఉన్నట్లు కనిపిస్తోంది. మళ్లీ కనెక్ట్ చేసి తనిఖీ చేయండి.", + "notCheckedYetHint": "Flo Cafe ఇంకా అప్డేట్ల కోసం తనిఖీ చేయలేదు.", + "devModeTitle": "డెవలప్మెంట్ బిల్డ్", + "updateErrorManifestMissing": "ఈ బిల్డ్ కోసం అప్డేట్ ప్యాకేజీ కనుగొనబడలేదు.", + "updateErrorDownloadFailed": "అప్డేట్ డౌన్లోడ్ విఫలమైంది. తదుపరి తనిఖీ సమయంలో మళ్లీ ప్రయత్నిస్తుంది.", + "updateErrorGeneric": "అప్డేట్ల కోసం తనిఖీ చేస్తున్నప్పుడు ఏదో తప్పు జరిగింది.", + "errorDetails": "వివరాలు", + "updates": "అప్డేట్లు", + "verificationEmailFailed": "ధృవీకరణ ఇమెయిల్ పంపడం సాధ్యం కాలేదు", + "verificationEmailQueued": "ధృవీకరణ ఇమెయిల్ క్యూలో పెట్టబడింది", + "verifyPinDescription": "ఈ చర్యకు మీ పరికర మాస్టర్ PIN అవసరం.", + "version": "వెర్షన్", + "viewTableInfo": "టేబుల్ సమాచారాన్ని చూడండి", + "vpnMeshNetwork": "VPN / మెష్ నెట్వర్క్", + "vpnMeshNetworkHint": "పరికరాలు వేర్వేరు సబ్నెట్లు లేదా లొకేషన్ల మధ్య VPN లేదా మెష్ నెట్వర్క్ ద్వారా కనెక్ట్ అయినప్పుడు ఉపయోగించండి", + "waitingForApproval": "ఆమోదం కోసం వేచి ఉంది", + "webusbHint": "క్విక్ యాక్షన్ల కోసం, పేరు ఒక WebUSB పరికరం యొక్క ఉత్పత్తి పేరుతో ఖచ్చితంగా సరిపోలాలి. టూల్బార్ కనెక్ట్ బటన్తో దాన్ని కనెక్ట్ చేయండి. ఈ ఎంట్రీ పేపర్ వెడల్పును సేవ్ చేస్తుంది.", + "webusbTestHint": "WebUSB: పరీక్షించడానికి POS టూల్బార్లోని కనెక్ట్ బటన్ను ఉపయోగించండి.", + "whatsapp": "WhatsApp", + "whatsappSharing": "WhatsApp షేరింగ్", + "yes": "అవును", + "zeroNoLimit": "(0 = పరిమితి లేదు)", + "tabAppearance": "రూపం", + "viewOnlyNotice": "ఈ సెట్టింగ్లను మార్చే అనుమతి లేకుండా మీరు వీటిని చూస్తున్నారు, కాబట్టి ఇక్కడి నియంత్రణలు చదవడానికి మాత్రమే. మీరు మార్పు చేయాల్సి వస్తే యజమాని మీకు సెట్టింగ్ల అనుమతిని ఇవ్వగలరు.", + "themeTitle": "థీమ్", + "themeLight": "లైట్", + "themeDark": "డార్క్", + "themeSystem": "సిస్టమ్", + "restoreFromFile": "బ్యాకప్ పునరుద్ధరించండి", + "restoreFromFileHint": "ఈ కంప్యూటర్లో ఇప్పటికే బ్యాకప్ ఫైల్ ఉందా? డేటాబేస్పై స్వయంగా కాపీ చేసే బదులు దాన్ని ఇక్కడ ఎంచుకోండి.", + "restoreReplacesDetail": "పునరుద్ధరించడం వల్ల ఈ బ్యాకప్ తీసుకున్న తర్వాత జోడించిన ప్రతి ఆర్డర్, బిల్, ఉత్పత్తి మరియు కస్టమర్ రికార్డు భర్తీ చేయబడుతుంది.", + "restoreKeepsDetail": "సిబ్బంది ఖాతాలు, PINలు, ప్రింటర్లు మరియు సెట్టింగ్లు కూడా బ్యాకప్ నుండే వస్తాయి. అందరూ సైన్ అవుట్ చేయబడతారు మరియు జత చేసిన డిస్ప్లేలు మరియు పరికరాలను మళ్లీ జత చేయాలి.", + "restoreSafetyCopyDetail": "ఏదైనా మారకముందే, మీరు ఈ పునరుద్ధరణను రద్దు చేయడానికి వీలుగా Flo మీ ప్రస్తుత డేటా కాపీని భద్రపరుస్తుంది.", + "diagnosticsLocalOnlyHint": "ఆటోమేటిక్ రిపోర్టింగ్ ఆఫ్లో ఉంది. పరిమిత సమస్య ఆధారాలు ఈ పరికరంలోనే ఉంటాయి.", + "diagnosticsRecentFailures": "ఇటీవలి వైఫల్యాలు", + "diagnosticsRefresh": "రిఫ్రెష్", + "diagnosticsClear": "క్లియర్", + "diagnosticsNoFailures": "ఈ పరికరంలో ఎలాంటి సమస్యలు నమోదు కాలేదు.", + "diagnosticsSupportBundle": "సపోర్ట్ కోసం కాపీ చేయండి", + "diagnosticsCopyForSupport": "సపోర్ట్ కోసం కాపీ చేయండి", + "diagnosticsBundleHint": "కాపీ బటన్ మీ క్లిప్బోర్డ్లో ఉంచేది ఖచ్చితంగా ఇదే. షేర్ చేసే ముందు దీన్ని సమీక్షించండి.", + "diagnosticsIncludeLogTail": "లాగ్ ఫైల్ను కూడా చేర్చండి", + "diagnosticsIncludeLogTailHint": "లాగ్ ఫైల్లో ఆర్డర్ మరియు కస్టమర్ వివరాలు ఉండవచ్చు, కాబట్టి మీరు ఇక్కడ అడిగితే తప్ప అది చేర్చబడదు.", + "diagnosticsLogTailLabel": "--- లాగ్ ఫైల్ (ఆర్డర్ మరియు కస్టమర్ వివరాలు ఉండవచ్చు) ---", + "diagnosticsBundleEmpty": "కాపీ చేయడానికి ఇంకా ఏమీ లేదు.", + "diagnosticsCopied": "కాపీ చేయబడింది. దీన్ని మీ సపోర్ట్ సందేశంలో పేస్ట్ చేయండి.", + "diagnosticsCopyFailed": "కాపీ చేయడం సాధ్యం కాలేదు. టెక్స్ట్ను ఎంచుకుని మాన్యువల్గా కాపీ చేయండి.", + "diagnosticsLoadFailed": "డయాగ్నస్టిక్స్ లోడ్ చేయడం సాధ్యం కాలేదు.", + "diagnosticsCleared": "నమోదైన సమస్యలు క్లియర్ చేయబడ్డాయి.", + "diagnosticsSettingSaved": "సెట్టింగ్ సేవ్ చేయబడింది.", + "diagnosticsSaveFailed": "సెట్టింగ్ను సేవ్ చేయడం సాధ్యం కాలేదు.", + "diagnosticsTransmission": "డయాగ్నస్టిక్స్ ఆటోమేటిక్గా పంపుతోంది", + "diagnosticsSendAutomatically": "డయాగ్నస్టిక్స్ ఆటోమేటిక్గా పంపండి", + "diagnosticsSendAutomaticallyHint": "ఇది మరియు స్టోర్ డయాగ్నస్టిక్స్ ఆన్లో ఉన్నప్పుడు, FloCafe పరిమితమైన, నిర్దిష్ట సమస్య నివేదికలను పంపగలదు. పంపడాన్ని ఆపడానికి ఏ ఒక్కదాన్నైనా ఆఫ్ చేయండి; లోకల్ ఆధారాలు ఈ పరికరంలోనే ఉంటాయి. నివేదికలలో కస్టమర్ మరియు చెల్లింపు వివరాలు ఉండవు. మాన్యువల్ సపోర్ట్ టికెట్లు వేరుగా ఉంటాయి.", + "diagnosticsTicketUnaffected": "ఇది ఆన్లో ఉన్నా లేకపోయినా, మీరు స్వయంగా వేసి పంపే సపోర్ట్ అభ్యర్థన ఎల్లప్పుడూ పనిచేస్తుంది.", + "diagnosticsLocalOnlyHintTransmitting": "రెండు గోప్యతా నియంత్రణల ద్వారా ఆటోమేటిక్ రిపోర్టింగ్ ప్రారంభించబడింది. క్రింద చూపిన మార్గం ద్వారా సురక్షితమైన, పరిమిత నివేదికలు పంపబడవచ్చు.", + "diagnosticsLocalOnlyHintPending": "రిపోర్టింగ్ అనుమతి లేదా డెలివరీ స్థితి ఇంకా నిర్ధారించబడలేదు.", + "diagnosticsConsentSyncPending": "గోప్యతా సెట్టింగ్ సింక్ కోసం వేచి ఉంది. అది నిర్ధారించబడే వరకు నివేదికలు పంపబడవు.", + "diagnosticsTransportState": "రిపోర్టింగ్ మార్గం: {transport}.", + "diagnosticsDeliveryDelayed": "డెలివరీ కోసం వేచి ఉన్నవి: {reports, plural, one {# నివేదిక} other {# నివేదికలు}} ({occurrences} సంఘటనలు) మరియు {aggregates, plural, one {# సారాంశం} other {# సారాంశాలు}} ({aggregateOccurrences} స్వీకరించిన సంఘటనలు).", + "diagnosticsPermanentRejections": "{count, plural, one {# నివేదిక శాశ్వతంగా తిరస్కరించబడింది} other {# నివేదికలు శాశ్వతంగా తిరస్కరించబడ్డాయి}}.", + "diagnosticsGapCount": "నమోదైన {count} సంఘటనలు డెలివరీ చేయబడలేదు: {reason}.", + "diagnosticsTransportSigned": "సంతకం చేసిన స్టోర్ నివేదికలు", + "diagnosticsTransportAnonymous": "అజ్ఞాత గణనలు", + "diagnosticsTransportLocal": "లోకల్ మాత్రమే", + "diagnosticsTransportDisabled": "నిలిపివేయబడింది", + "diagnosticsGapQueueEviction": "లోకల్ క్యూ తన పరిమితిని చేరుకుంది", + "diagnosticsGapPermanentRejection": "స్వీకర్త నివేదికను శాశ్వతంగా తిరస్కరించారు", + "diagnosticsGapInvalidAck": "స్వీకర్త చెల్లని రసీదును తిరిగి పంపారు", + "diagnosticsGapReportMismatch": "స్వీకర్త వేరొక నివేదిక ID ని తిరిగి పంపారు", + "diagnosticsGapLocalRetention": "లోకల్ ఆధారాలు స్టోరేజ్ పరిమితిని మించిపోయాయి", + "diagnosticsLocalRetentionGap": "పరికర చరిత్ర తన పరిమితిని చేరుకున్నందున {count} లోకల్ డయాగ్నస్టిక్ సంఘటనలు కోల్పోయాయి.", + "printing": "ప్రింటింగ్", + "requireKitchenDeliveredToggle": "బిల్లింగ్కు ముందు కిచెన్ డెలివరీ తప్పనిసరి", + "requireKitchenDeliveredHint": "కిచెన్లో అన్ని ఐటెమ్లు వడ్డించినట్లు మార్క్ చేయబడే వరకు పోస్ట్పెయిడ్ బిల్లులను సెటిల్ చేయకుండా నిరోధించండి. KDS నిలిపివేయబడితే ఆటోమేటిక్గా దాటవేయబడుతుంది.", + "ordersLayoutTitle": "ఆర్డర్ల స్క్రీన్ లేఅవుట్", + "ordersLayoutSplit": "మాస్టర్ / వివరాలు (స్ప్లిట్ వ్యూ)", + "ordersLayoutSplitHint": "ఎడమవైపు సంక్షిప్త ఆర్డర్ జాబితా మరియు కుడివైపు పూర్తి ఆర్డర్ వివరాలు.", + "ordersLayoutCards": "కార్డుల గ్రిడ్", + "ordersLayoutCardsHint": "విడివిడి ఆర్డర్ కార్డుల క్లాసిక్ గ్రిడ్.", + "posSortTitle": "POS మెనూ క్రమబద్ధీకరణ", + "posSortHint": "POS మరియు సర్వర్ యాప్లో కేటగిరీలు మరియు ఐటెమ్లు ఎలా క్రమబద్ధీకరించబడాలో నియంత్రిస్తుంది.", + "posCategorySortLabel": "కేటగిరీలు", + "posItemSortLabel": "మెనూ ఐటెమ్లు", + "posSort_saved": "సేవ్ చేసిన విధంగా (మాన్యువల్ క్రమం)", + "posSort_name": "అక్షర క్రమం (A–Z)", + "posSort_price_asc": "ధర: తక్కువ నుండి ఎక్కువ", + "posSort_price_desc": "ధర: ఎక్కువ నుండి తక్కువ", + "chargesAndSurcharges": "ఛార్జీలు & సర్ఛార్జీలు", + "chargesAndSurchargesHint": "ఆర్డర్లకు ఆటోమేటిక్గా వర్తించే సర్వీస్ ఛార్జీలు, ప్యాకేజింగ్ ఫీజులు మరియు సర్ఛార్జీలు.", + "noChargesConfigured": "ఇంకా ఛార్జీలు కాన్ఫిగర్ చేయబడలేదు.", + "addCharge": "ఛార్జీ జోడించండి", + "deleteChargeConfirm": "{name} ను తొలగించాలా? ఇప్పటికే బిల్ చేసిన ఆర్డర్లలో వాటిపై నమోదైన ఛార్జీలు అలాగే ఉంటాయి.", + "chargesSaved": "ఛార్జీలు సేవ్ చేయబడ్డాయి", + "chargesSaveFailed": "ఛార్జీలను సేవ్ చేయడం సాధ్యం కాలేదు", + "chargeName": "పేరు", + "chargeType": "రకం", + "chargeTypePercentage": "శాతం", + "chargeTypeFixed": "స్థిర మొత్తం", + "chargeValue": "విలువ", + "chargeBasis": "లెక్కింపు ఆధారం", + "chargeBasisNet": "నెట్ (తగ్గింపు తర్వాత)", + "chargeBasisGross": "గ్రాస్ (తగ్గింపుకు ముందు)", + "chargeOrderTypes": "వర్తించే ఆర్డర్ రకాలు", + "chargeWaivable": "క్యాషియర్ మినహాయించవచ్చు", + "chargeAutoApply": "ఆటోమేటిక్గా వర్తింపజేయి", + "chargePercentValue": "ఆర్డర్లో {value}%", + "chargeFixedValue": "ఆర్డర్కు {value}", + "chargeOptionalApply": "అభ్యర్థనపై జోడించబడుతుంది", + "storeLogo": "స్టోర్ లోగో", + "storeLogoHint": "థర్మల్ రసీదులు మరియు బ్రౌజర్ బిల్లులపై ప్రింట్ చేయడానికి స్టోర్ లోగోను అప్లోడ్ చేయండి. 5 MB లోపు పారదర్శక PNG లేదా JPEG. ఆటోమేటిక్గా 1-బిట్ థర్మల్ రాస్టర్గా మార్చబడుతుంది.", + "uploadLogo": "లోగో అప్లోడ్ చేయండి", + "removeLogo": "లోగో తొలగించండి", + "logoUploaded": "లోగో విజయవంతంగా అప్లోడ్ చేయబడింది", + "showLogo": "స్టోర్ లోగో", + "chargeKind": "ఫీజు రకం", + "chargePresetCustom": "కస్టమ్", + "editCharge": "ఛార్జీ సవరించండి", + "chargeReopenRequired": "ఈ ఛార్జీ ఇకపై అందుబాటులో లేదు. దయచేసి మళ్లీ తెరిచి ప్రయత్నించండి.", + "offlineModeTitle": "ఆఫ్లైన్ మోడ్", + "offlineModeDescription": "ప్రతి ఐచ్ఛిక ఇంటర్నెట్ కనెక్షన్ను ఆఫ్ చేస్తుంది: క్లౌడ్ సింక్, Google Drive బ్యాకప్లు, WhatsApp, అప్డేట్ తనిఖీలు, వినియోగ విశ్లేషణలు మరియు వెబ్ నుండి చిత్ర దిగుమతి. ఆర్డర్లు, బిల్లింగ్, ప్రింటింగ్ మరియు మీ లోకల్ నెట్వర్క్లోని పరికరాలు పనిచేస్తూనే ఉంటాయి.", + "offlineModeFailed": "ఆఫ్లైన్ మోడ్ను మార్చడం సాధ్యం కాలేదు", + "offlineModeReadFailed": "ప్రస్తుత ఆఫ్లైన్ మోడ్ సెట్టింగ్ను చదవడం సాధ్యం కాలేదు.", + "offlineModeRetry": "మళ్లీ ప్రయత్నించు", + "autoLockLabel": "నిష్క్రియ ఆటో-లాక్", + "autoLockHint": "నిష్క్రియత తర్వాత POS టెర్మినల్ను ఆటోమేటిక్గా లాక్ చేయండి", + "autoLockOff": "ఆఫ్", + "autoLockMinutesOption": "{count} నిమి", + "requireOpenShift": "నగదు కోసం ఓపెన్ షిఫ్ట్ తప్పనిసరి", + "requireOpenShiftHint": "యాక్టివ్ షిఫ్ట్ తెరిచి ఉంటే తప్ప నగదు చెల్లింపులు, నగదు రీఫండ్లు మరియు డ్రాయర్ లావాదేవీలను నిరోధించండి.", + "oneShiftPerStaff": "ప్రతి సిబ్బంది సభ్యునికి ఒక షిఫ్ట్", + "oneShiftPerStaffHint": "ప్రతి సిబ్బంది సభ్యుడు తమ స్వంత క్యాష్ షిఫ్ట్ను స్వతంత్రంగా తెరవడానికి మరియు మూసివేయడానికి అనుమతించండి.", + "oneShiftPerStaffSharedDrawerWarning": "గమనిక: రెండు ఏకకాల షిఫ్ట్లు ఒకే భౌతిక క్యాష్ డ్రాయర్ను పంచుకుంటే, వ్యక్తిగత డ్రాయర్ నగదు లెక్కలు భౌతికంగా వేరు చేయబడవు.", + "oneShiftPerStaffDisableBlocked": "బహుళ షిఫ్ట్లు తెరిచి ఉన్నప్పుడు ప్రతి సిబ్బంది సభ్యునికి ఒక షిఫ్ట్ ఎంపికను నిలిపివేయలేరు. ముందుగా అదనపు షిఫ్ట్లను మూసివేయండి.", + "tabCounters": "కౌంటర్లు", + "counterRoleOrdering": "ఆర్డరింగ్", + "counterRolePayment": "చెల్లింపు", + "counterRoleCombined": "కంబైన్డ్", + "ownerPermissionRequired": "కౌంటర్లను నిర్వహించడానికి యజమాని అనుమతి అవసరం.", + "multiCounterEnabled": "మల్టీ-కౌంటర్ ఆర్డరింగ్ ప్రారంభించబడింది", + "multiCounterDisabled": "మల్టీ-కౌంటర్ ఆర్డరింగ్ నిలిపివేయబడింది", + "counterUpdated": "కౌంటర్ అప్డేట్ చేయబడింది", + "counterCreated": "కౌంటర్ సృష్టించబడింది", + "counterDeleted": "కౌంటర్ తొలగించబడింది", + "multiCounterTitle": "మల్టీ-కౌంటర్ ఆర్డరింగ్", + "multiCounterDesc": "వేర్వేరు ఆర్డర్ సృష్టి మరియు చెల్లింపు వర్క్ఫ్లోల కోసం ఆర్డరింగ్ మరియు చెల్లింపు కౌంటర్లను కాన్ఫిగర్ చేయండి.", + "namedCounters": "పేరు పెట్టబడిన కౌంటర్లు", + "namedCountersHint": "ప్రతి POS స్టేషన్ తన కౌంటర్ పాత్రను ఎంచుకుంటుంది: ఆర్డరింగ్, చెల్లింపు లేదా కంబైన్డ్.", + "addCounter": "కౌంటర్ జోడించండి", + "editCounter": "కౌంటర్ సవరించండి", + "counterModalDesc": "కౌంటర్ పేరు మరియు కార్యాచరణ పాత్రను సెట్ చేయండి.", + "counterName": "కౌంటర్ పేరు", + "counterRole": "కౌంటర్ పాత్ర", + "counterIsActive": "యాక్టివ్", + "confirmDeleteCounter": "ఈ కౌంటర్ను తొలగించాలా?", + "confirmDeleteCounterDesc": "ఈ కౌంటర్ శాశ్వతంగా తొలగించబడుతుంది." + }, + "setup": { + "alreadyCompleted": "ఈ ఇన్స్టాల్లో సెటప్ ఇప్పటికే పూర్తయింది. లాగిన్కు మళ్లిస్తోంది…", + "back": "వెనుకకు", + "businessName": "రెస్టారెంట్ పేరు", + "businessNamePlaceholder": "రెస్టారెంట్ పేరు", + "chooseCountry": "మీ దేశాన్ని ఎంచుకోండి", + "chooseCountryHint": "సరైన కరెన్సీ, పన్ను ఫార్మాట్ మరియు డెమో డేటాను ఎంచుకోవడానికి FloCafe మీ దేశాన్ని ఉపయోగిస్తుంది.", + "chooseCountryRequired": "కొనసాగించడానికి మీ దేశాన్ని ఎంచుకోండి", + "chooseLanguage": "మీ భాషను ఎంచుకోండి", + "chooseLanguageHint": "దేశాన్ని ఎంచుకునే ముందు ఈ సెటప్ కోసం భాషను ఎంచుకోండి.", + "cloudEnableHint": "క్లౌడ్ సేవలు ఐచ్ఛికం మరియు డిఫాల్ట్గా ఆఫ్లో ఉంటాయి. RevFlo రిపోర్టింగ్, పరికర జత చేయడం మరియు మద్దతు ఉన్న ఖాతా సేవల వంటి ఫీచర్ల కోసం FloCafeను FloAdminతో కనెక్ట్ చేయడానికి వాటిని ఆన్ చేయండి.", + "cloudEnableLabel": "క్లౌడ్ సేవలను ఆన్ చేయి", + "cloudRecoveryNoteDisabled": "క్లౌడ్ సేవలు నిలిపివేయబడ్డాయి. ఈ ఇన్స్టాల్లో పాస్వర్డ్ రికవరీ మునుపటి దశలో సెట్ చేసిన మాస్టర్ పిన్పై ఆధారపడి ఉంటుంది. మీరు మీ పాస్వర్డ్ మరియు మాస్టర్ పిన్ రెండింటినీ మర్చిపోతే, రికవరీకి స్థానిక డేటాబేస్ రీఇనిషియలైజేషన్ (సెట్టింగ్లు → డేటాబేస్ టూల్స్) అవసరం, ఇది తప్పనిసరి బ్యాకప్ తర్వాత స్థానిక డేటాను తుడిచివేస్తుంది.", + "cloudRecoveryNoteEnabled": "ఈమెయిల్ ఆధారిత పాస్వర్డ్ రీసెట్కు క్లౌడ్ సేవలు ఆన్లో ఉండాలి, ధృవీకరించిన యజమాని ఈమెయిల్ మరియు ఇంటర్నెట్ కనెక్షన్ అవసరం. మాస్టర్ పిన్ రికవరీ ఆఫ్లైన్లో పనిచేస్తుంది.", + "cloudSubtitle": "ఐచ్ఛికం. సెల్ఫ్-హోస్టెడ్ లేదా కస్టమ్ డిప్లాయ్మెంట్లు డిఫాల్ట్ Flo క్లౌడ్కు బదులుగా తమ స్వంత సర్వర్ను సూచించవచ్చు.", + "cloudManagedAutomaticallyDescription": "FloCafe స్వయంచాలకంగా కనెక్ట్ అవుతుంది కాబట్టి మాన్యువల్ ఆమోద దశ లేకుండా RevFlo జత చేయడం మరియు మద్దతు పనిచేస్తాయి.", + "cloudManagedAutomaticallyTitle": "క్లౌడ్ సేవలు స్వయంచాలకంగా ఆన్ చేయబడ్డాయి", + "cloudTitle": "క్లౌడ్ సేవలు", + "cloudUrlHint": "డిఫాల్ట్ Flo క్లౌడ్ సర్వర్తో ముందే నింపబడింది. సెల్ఫ్-హోస్టెడ్ లేదా కస్టమ్ డిప్లాయ్మెంట్ల కోసం సవరించవచ్చు.", + "cloudUrlHttpsRequired": "క్లౌడ్ సర్వర్ URL తప్పనిసరిగా HTTPS ఉపయోగించాలి (లేదా డెవలప్మెంట్ కోసం స్థానిక HTTP)", + "cloudUrlInvalid": "దయచేసి చెల్లబాటు అయ్యే క్లౌడ్ సర్వర్ URL నమోదు చేయండి", + "cloudUrlLabel": "క్లౌడ్ సర్వర్ URL", + "completeSetup": "సెటప్ పూర్తి చేయి", + "completeSetupSuccess": "సెటప్ పూర్తయింది", + "completingSetup": "సెటప్ పూర్తి చేస్తోంది…", + "confirmPassword": "పాస్వర్డ్ నిర్ధారించండి", + "confirmPasswordPlaceholder": "పాస్వర్డ్ మళ్లీ నమోదు చేయండి", + "confirmPinLabel": "పిన్ నిర్ధారించండి", + "continue": "కొనసాగించు", + "createOwner": "యజమాని ఖాతా సృష్టించు", + "demoDesc": "శిక్షణ మరియు పరీక్ష కోసం నమూనా డేటా.", + "demoDetails": "క్లయింట్ సిస్టమ్ను అన్వేషించడానికి ఉత్పత్తులు, టేబుళ్లు, నమూనా కస్టమర్లు మరియు సిబ్బంది వినియోగదారులను జోడిస్తుంది.", + "demoLabel": "డెమో", + "disclaimer": "వారంటీ నిరాకరణ", + "emptyDesc": "యజమాని ఖాతా మరియు అవసరమైన సెట్టింగ్లు మాత్రమే.", + "emptyDetails": "క్లయింట్ ప్రతి ఉత్పత్తి, టేబుల్ మరియు కస్టమర్ను మాన్యువల్గా నమోదు చేయాలనుకున్నప్పుడు దీన్ని ఉపయోగించండి.", + "emptyLabel": "ఖాళీ", + "errorGeneric": "సెటప్ పూర్తి చేయడం విఫలమైంది", + "errorInvalidEmail": "చెల్లబాటు అయ్యే ఈమెయిల్ చిరునామాను నమోదు చేయండి.", + "errorNameRequired": "పేరు, ఈమెయిల్ మరియు పాస్వర్డ్ తప్పనిసరి", + "errorPasswordMismatch": "పాస్వర్డ్లు సరిపోలడం లేదు", + "errorPasswordRequirementsNotMet": "పాస్వర్డ్ కనీసం 4 అక్షరాల పొడవు ఉండాలి.", + "errorTermsRequired": "కొనసాగించడానికి మీరు నిబంధనలు మరియు షరతులు, గోప్యతా విధానం మరియు వారంటీ నిరాకరణకు అంగీకరించాలి", + "emailCommunicationDescription": "ఈ చిరునామాను మీరు ధృవీకరించడానికి మేము వెంటనే ఆహ్వాన ఈమెయిల్ పంపుతాము. ముఖ్యమైన ఖాతా, సేవ మరియు భద్రతా నోటీసులు ప్రమోషనల్ కావు మరియు ఇక్కడ నిలిపివేయబడవు.", + "emailCommunicationTitle": "ఈమెయిల్ కమ్యూనికేషన్", + "expressBadge": "సిఫార్సు చేయబడింది", + "expressDesc": "అమ్మకానికి సిద్ధంగా ఉన్న కనీస రెస్టారెంట్ సెటప్.", + "expressDetails": "FineDine కోసం ప్రాథమిక ఆహారం మరియు పానీయాల వర్గాలు, కొన్ని ప్రారంభ ఉత్పత్తులు మరియు టేబుళ్లను జోడిస్తుంది.", + "expressLabel": "ఎక్స్ప్రెస్", + "finedineDesc": "టేబుల్ నిర్వహణ మరియు పోస్ట్పెయిడ్ బిల్లింగ్", + "finedineDetails": "అతిథులను కూర్చోబెట్టి, టేబుళ్లను నిర్వహించి, సేవ తర్వాత చెల్లింపు వసూలు చేసే రెస్టారెంట్లకు ఉత్తమమైనది.", + "finedineLabel": "ఫైన్డైన్", + "flowSubtitle": "FloCafe రెస్టారెంట్ల కోసం మాత్రమే. ఈ అవుట్లెట్ కోసం బిల్లింగ్ మోడల్ను ఎంచుకోండి.", + "flowTitle": "రెస్టారెంట్ ఫ్లో ఎంచుకోండి", + "languageEnglish": "ఇంగ్లీష్", + "languagePersian": "పర్షియన్", + "languagePortuguese": "పోర్చుగీస్", + "languageSpanish": "స్పానిష్", + "marketingOptional": "మార్కెటింగ్ సందేశాలు, ఆఫర్లు మరియు సర్వేలను అందుకోండి (ఐచ్ఛికం)", + "productUpdatesOptional": "ఉత్పత్తి అప్డేట్లు మరియు రిలీజ్ నోట్లను అందుకోండి (ఐచ్ఛికం)", + "masterPinNotAvailable": "ఈ పరికరంలో మాస్టర్ పిన్ రక్షణ అందుబాటులో లేదు. మీరు అది లేకుండా కొనసాగవచ్చు.", + "masterPinRecoveryNote": "మీరు ఎప్పుడైనా మీ లాగిన్ పాస్వర్డ్ మర్చిపోతే తర్వాత యాక్సెస్ పునరుద్ధరించడానికి కూడా ఈ పిన్ ఉపయోగపడుతుంది — లాగిన్ స్క్రీన్ నుండి, \"పాస్వర్డ్ మర్చిపోయారా? యాక్సెస్ పునరుద్ధరించండి\" ఎంచుకుని, కొత్త పాస్వర్డ్ సెట్ చేయడానికి మీ ఈమెయిల్తో పాటు ఈ పిన్ నమోదు చేయండి.", + "masterPinRequired": "కొనసాగించడానికి 4-అంకెల మాస్టర్ పిన్ సెట్ చేయండి", + "ownerApprovalPinDescription": "రీఫండ్లను ఆమోదించడానికి యజమాని ఈ 4-6 అంకెల పిన్ను ఉపయోగిస్తారు. ఇది పరికరం మాస్టర్ పిన్ నుండి వేరుగా ఉంటుంది.", + "ownerApprovalPinLabel": "యజమాని ఆమోద పిన్", + "ownerApprovalPinMismatch": "యజమాని ఆమోద పిన్లు సరిపోలడం లేదు", + "ownerApprovalPinRequired": "4-6 అంకెల యజమాని ఆమోద పిన్ నమోదు చేసి నిర్ధారించండి", + "noMatches": "“{query}” కు సరిపోయే దేశాలు లేవు", + "noTaxId": "పన్ను ఐడి లేదు", + "ownerEmail": "యజమాని ఈమెయిల్", + "ownerEmailDomainWarning": "ఈ ఈమెయిల్ డొమైన్ మెయిల్ అందుకోకపోవచ్చు. మీరు కొనసాగవచ్చు, కానీ కీలకమైన సాఫ్ట్వేర్ నోటీసులు మరియు ఖాతా రికవరీ సందేశాలు మీకు చేరకపోవచ్చు.", + "ownerEmailPlaceholder": "owner@restaurant.com", + "ownerName": "యజమాని పేరు", + "ownerNamePlaceholder": "యజమాని పేరు", + "ownerSubtitle": "ఈ మొదటి వినియోగదారుకు ఈ POSలో పూర్తి యజమాని యాక్సెస్ లభిస్తుంది.", + "password": "పాస్వర్డ్", + "passwordPlaceholder": "పాస్వర్డ్ నమోదు చేయండి", + "passwordsMatch": "పాస్వర్డ్లు సరిపోలాయి", + "passwordsMismatch": "పాస్వర్డ్లు సరిపోలడం లేదు", + "pinLabel": "పిన్", + "privacy": "గోప్యతా విధానం", + "qsrDesc": "ప్రీపెయిడ్ కౌంటర్ సేవ", + "qsrDetails": "ఆర్డర్ అందించే ముందే చెల్లింపు తీసుకునే క్విక్-సర్వీస్ రెస్టారెంట్లకు ఉత్తమమైనది.", + "qsrLabel": "QSR", + "searchPlaceholder": "దేశం, కరెన్సీ, లోకేల్ వెతకండి…", + "setMasterPinDescription": "మీకు మాత్రమే తెలిసిన 4-అంకెల పిన్, ఈ డేటాబేస్ను బ్యాకప్ చేయడానికి, పునరుద్ధరించడానికి లేదా ఇనిషియలైజ్ చేయడానికి అవసరం — మీ లాగిన్ పాస్వర్డ్ నుండి వేరుగా ఉంటుంది. మీరు దీన్ని మర్చిపోతే, యజమానిగా లాగిన్ అయి ఉన్నప్పుడు సెట్టింగ్ల నుండి తర్వాత రీసెట్ చేయవచ్చు.", + "setMasterPinTitle": "మాస్టర్ పిన్ సెట్ చేయండి", + "setupDataSubtitle": "మొదటిసారి ప్రారంభించినప్పుడు ఎంత డేటా సృష్టించాలో ఎంచుకోండి.", + "setupDataTitle": "సెటప్ డేటా ఎంచుకోండి", + "tagline": "యజమాని ఖాతాను సృష్టించి రెస్టారెంట్ సెటప్ను ఎంచుకోండి.", + "terms": "నిబంధనలు మరియు షరతులు", + "termsAnd": "మరియు", + "termsIntro": "నేను FloPOS యొక్క", + "timezoneHint": "మీ దేశం నుండి ముందే నింపబడింది. బహుళ-టైమ్జోన్ దేశాలలోని స్టోర్లు తమ వాస్తవ స్థానిక టైమ్జోన్ను ఎంచుకోవచ్చు.", + "timezoneLabel": "టైమ్జోన్", + "welcome": "FloCafe కు స్వాగతం" + }, + "staff": { + "addButton": "సిబ్బందిని జోడించు", + "addedToast": "సిబ్బంది జోడించబడ్డారు", + "deactivate": "డీయాక్టివేట్ చేయి", + "empty": "ఇంకా సిబ్బంది ఎవరూ లేరు", + "failedToLoad": "సిబ్బందిని లోడ్ చేయడం విఫలమైంది", + "failedToReset": "పాస్వర్డ్ రీసెట్ చేయడం విఫలమైంది", + "failedToSave": "సేవ్ చేయడం విఫలమైంది", + "failedToUpdate": "అప్డేట్ చేయడం విఫలమైంది", + "kitchenStationsOptional": "కిచెన్ స్టేషన్లు (ఐచ్ఛికం)", + "kitchenStationsOptionalHint": "ఒకటి లేదా అంతకంటే ఎక్కువ స్టేషన్లను ఎంచుకోండి, లేదా స్టేషన్ పరిమితి లేకుండా ఉండటానికి దీన్ని ఖాళీగా ఉంచండి.", + "kitchenStationsRequireKds": "కిచెన్ స్టేషన్లను కేటాయించడానికి సెట్టింగ్లలో KDS ఆన్ చేయండి.", + "modalTitleAdd": "సిబ్బందిని జోడించు", + "modalTitleEdit": "సిబ్బందిని సవరించు", + "namePlaceholder": "పేరు", + "newPasswordPlaceholder": "కొత్త పాస్వర్డ్ (అలాగే ఉంచడానికి ఖాళీగా వదిలేయండి)", + "noKitchenStations": "కిచెన్ స్టేషన్లు ఏవీ అందుబాటులో లేవు", + "passwordPlaceholder": "పాస్వర్డ్", + "pinHint": "త్వరిత సైన్-ఇన్ మరియు యజమాని/మేనేజర్ ఆమోదాల కోసం ఉపయోగించబడుతుంది", + "pinPlaceholderAdd": "పిన్ (4-6 అంకెలు)", + "pinPlaceholderEdit": "కొత్త పిన్ (అలాగే ఉంచడానికి ఖాళీగా వదిలేయండి)", + "pinSet": "✓ పిన్ సెట్ చేయబడింది", + "reactivate": "రీయాక్టివేట్ చేయి", + "resetPasswordBody": "{name} కోసం పాస్వర్డ్ రీసెట్ చేయి", + "resetPasswordTitle": "పాస్వర్డ్ రీసెట్ చేయి", + "resetPasswordToast": "పాస్వర్డ్ విజయవంతంగా రీసెట్ చేయబడింది", + "resetPwButton": "పాస్వర్డ్ రీసెట్", + "roleCashier": "క్యాషియర్", + "roleChef": "చెఫ్ (KDS)", + "roleManager": "మేనేజర్", + "roleOwner": "యజమాని", + "roleServer": "సర్వర్", + "title": "సిబ్బంది", + "updateButton": "అప్డేట్", + "updatedToast": "సిబ్బంది అప్డేట్ చేయబడ్డారు" + }, + "permissionMatrix": { + "title": "పాత్ర అనుమతులు", + "description": "ప్రతి స్థిర పాత్ర వేటిని యాక్సెస్ చేయగలదో చూపే రీడ్-ఓన్లీ అవలోకనం.", + "caption": "సామర్థ్యం వారీగా FloCafe పాత్ర అనుమతులు", + "capabilityHeader": "సామర్థ్యం", + "allowed": "అనుమతించబడింది", + "notAllowed": "అనుమతించబడలేదు", + "fixedNote": "ఈ అనుమతులు ప్రస్తుతం పాత్ర ఆధారంగా స్థిరంగా ఉంటాయి. పాత్ర కాన్ఫిగరేషన్/IAM ఇంకా అందుబాటులో లేదు.", + "ownerDescription": "పూర్తి యాక్సెస్", + "managerDescription": "కార్యకలాపాల మేనేజర్", + "cashierDescription": "POS మరియు చెల్లింపులు", + "serverDescription": "ఆర్డర్లు మరియు టేబుళ్లు", + "chefDescription": "కిచెన్ డిస్ప్లే", + "areas": { + "tables": "టేబుళ్లు", + "cash": "నగదు", + "inventory": "స్టాక్ మరియు రెసిపీలు", + "authorization": "అనుమతులు", + "tax": "పన్ను", + "printing": "ప్రింటింగ్", + "apps": "యాప్లు", + "orders": "ఆర్డర్లు", + "payments": "చెల్లింపులు", + "customers": "కస్టమర్లు", + "menu": "మెనూ", + "kitchen": "వంటగది", + "reports": "నివేదికలు", + "staff": "సిబ్బంది", + "settings": "సెట్టింగ్లు", + "integrations": "ఇంటిగ్రేషన్లు", + "system": "సిస్టమ్", + "support": "మద్దతు" + }, + "capabilities": { + "tablesView": "టేబుళ్లు చూడటం", + "refunds": "రీఫండ్లు జారీ చేయడం", + "cashShiftsView": "నగదు షిఫ్ట్లు చూడటం", + "cashMovements": "నగదు లావాదేవీలను నమోదు చేయడం మరియు రద్దు చేయడం", + "cashDayClose": "వ్యాపార రోజును ముగించడం", + "inventoryView": "స్టాక్ మరియు రెసిపీలు చూడటం", + "kitchenStatusUpdate": "కిచెన్ డిస్ప్లేలో ఆర్డర్ స్థితిని అప్డేట్ చేయడం", + "reportsDailySalesExport": "రోజువారీ అమ్మకాల నివేదికను ఎగుమతి చేయడం", + "reportsCustomerSalesExport": "ఐటెమ్ వివరాలతో కస్టమర్ అమ్మకాలను ఎగుమతి చేయడం", + "authorizationManage": "పాత్ర అనుమతులు మరియు సిబ్బంది యాక్సెస్ మార్చడం", + "mobileAccessManage": "మొబైల్ పరికర యాక్సెస్ నిర్వహించడం", + "pos": "POS టెర్మినల్ ఉపయోగించడం", + "dashboard": "యజమాని డ్యాష్బోర్డ్ చూడటం", + "ordersReadCreate": "ఆర్డర్లు చూడటం మరియు సృష్టించడం", + "ordersStatus": "ఆర్డర్ స్థితిని అప్డేట్ చేయడం", + "ordersCustomerDiscounts": "ఆర్డర్ కస్టమర్లు మరియు తగ్గింపులను మార్చడం", + "orderItemCancel": "పెండింగ్ ఆర్డర్ ఐటెమ్లను రద్దు చేయడం", + "orderItemVoid": "తయారీలో ఉన్న ఆర్డర్ ఐటెమ్లను రద్దు చేయడం (మేనేజర్ పిన్ అవసరం కావచ్చు)", + "orderItemRestore": "రద్దు చేసిన ఆర్డర్ ఐటెమ్లను పునరుద్ధరించడం", + "orderItemEdit": "పరిమాణాన్ని సవరించడం లేదా ఆర్డర్ ఐటెమ్లను భర్తీ చేయడం", + "heldOrders": "హోల్డ్ చేసిన ఆర్డర్లను సృష్టించడం మరియు నిర్వహించడం", + "billsPayments": "బిల్లులు చూడటం, చెల్లింపులు తీసుకోవడం మరియు రసీదులు ప్రింట్ చేయడం", + "billDiscounts": "బిల్లు తగ్గింపులను వర్తింపజేయడం మరియు బిల్లులను ప్రింట్ చేసినట్లు గుర్తించడం", + "paymentMethodsView": "చెల్లింపు విధానాలు చూడటం", + "paymentMethodsManage": "చెల్లింపు విధానాలు నిర్వహించడం", + "expensesView": "ఖర్చులు మరియు బ్యాలెన్స్లు చూడటం", + "expensesManage": "ఖర్చు రికార్డులను సృష్టించడం మరియు సరిచేయడం", + "expensesPay": "ఖర్చు చెల్లింపులను నమోదు చేయడం", + "expensesReverse": "ఖర్చు చెల్లింపులను రివర్స్ చేయడం", + "printing": "బిల్లులు మరియు కిచెన్ టికెట్లు ప్రింట్ చేయడం", + "shiftOpen": "నగదు షిఫ్ట్ తెరవడం", + "shiftClose": "స్వంత నగదు షిఫ్ట్ ముగించడం (యజమాని/మేనేజర్ ఏదైనా ముగించవచ్చు)", + "customersViewCreate": "కస్టమర్లను చూడటం, వెతకడం మరియు సృష్టించడం", + "customersEdit": "కస్టమర్లను సవరించడం", + "customerMaintenance": "కస్టమర్ ఫోన్ రికార్డులను సరిచేయడం", + "customerCleanup": "కస్టమర్ రికార్డులను శుభ్రపరచడం", + "catalogManagement": "ఉత్పత్తులు, వర్గాలు మరియు యాడ్-ఆన్లను నిర్వహించడం", + "menuImportExport": "మెనూ డేటాను దిగుమతి మరియు ఎగుమతి చేయడం", + "tablesManage": "టేబుళ్లను నిర్వహించడం", + "tablesMoveOrders": "టేబుళ్ల మధ్య ఆర్డర్లను తరలించడం", + "kds": "కిచెన్ డిస్ప్లే సిస్టమ్ ఉపయోగించడం", + "kdsPairing": "కిచెన్ డిస్ప్లేను జత చేయడం", + "kitchenStations": "కిచెన్ స్టేషన్లు మరియు కేటాయింపులను నిర్వహించడం", + "reports": "అమ్మకాలు మరియు కార్యకలాపాల నివేదికలు చూడటం", + "staffViewManage": "సిబ్బంది ఖాతాలను చూడటం మరియు నిర్వహించడం", + "staffOwnerManager": "యజమాని మరియు మేనేజర్ ఖాతాలు మరియు పాత్రలను నిర్వహించడం", + "operationalStaff": "క్యాషియర్, సర్వర్ మరియు చెఫ్ ఖాతాలను నిర్వహించడం", + "settingsView": "స్టోర్ మరియు కార్యకలాపాల సెట్టింగ్లు చూడటం", + "settingsManage": "స్టోర్ మరియు కార్యకలాపాల సెట్టింగ్లు మార్చడం", + "taxPacksViewTest": "పన్ను ప్యాక్లను చూడటం మరియు పరీక్షించడం", + "taxPacksManage": "పన్ను ప్యాక్లను ఇన్స్టాల్ చేయడం, యాక్టివేట్ చేయడం మరియు నిర్వహించడం", + "taxConfiguration": "పన్ను కాన్ఫిగరేషన్ మార్చడం", + "printTemplatesView": "ప్రింట్ టెంప్లేట్లు చూడటం", + "printTemplatesManage": "ప్రింట్ టెంప్లేట్లు నిర్వహించడం", + "printersManage": "ప్రింటర్లను నిర్వహించడం", + "whatsappUse": "WhatsApp మెసేజింగ్ ఉపయోగించడం", + "whatsappManage": "WhatsApp కాన్ఫిగర్ చేయడం", + "cloudDrive": "క్లౌడ్ సెట్టింగ్లను నిర్వహించడం", + "googleDrive": "Google Drive బ్యాకప్లను నిర్వహించడం", + "cloudAccountData": "క్లౌడ్ ఖాతా మరియు డేటా నియంత్రణలను నిర్వహించడం", + "databaseTools": "డేటాబేస్ టూల్స్ మరియు బ్యాకప్లను ఉపయోగించడం", + "serverApp": "స్టాండ్అలోన్ సర్వర్ యాప్ ఉపయోగించడం", + "support": "సపోర్ట్ను సంప్రదించడం మరియు డయాగ్నస్టిక్స్ చూడటం", + "inventoryManage": "సరఫరాలు మరియు రెసిపీలను నిర్వహించడం", + "orderItemPriceOverride": "ఆర్డర్ ఐటెమ్ ధరలను మార్చడం", + "offlineMode": "ఆఫ్లైన్ మోడ్ ఆన్ లేదా ఆఫ్ చేయడం" + }, + "editorSubtitle": "పాత్ర డిఫాల్ట్లను కాన్ఫిగర్ చేయండి లేదా ఒక సిబ్బంది సభ్యుని కోసం మినహాయింపు ఇవ్వండి. మార్పులు వారి తదుపరి చర్యకు వర్తిస్తాయి.", + "roleDefaultsTab": "పాత్ర డిఫాల్ట్లు", + "staffExceptionTab": "సిబ్బంది మినహాయింపు", + "selectStaffPlaceholder": "సిబ్బంది సభ్యుని ఎంచుకోండి", + "selectStaffEmptyState": "వారి అనుమతులను సవరించడానికి సిబ్బంది సభ్యుని ఎంచుకోండి.", + "effectiveHeader": "అమలులో ఉన్నది", + "overrideHeader": "ఓవర్రైడ్", + "inherit": "వారసత్వం", + "allow": "అనుమతించు", + "deny": "నిరాకరించు", + "protected": "రక్షించబడింది", + "selfAccessWarningAuthorization": "దీన్ని సేవ్ చేయడం వల్ల సిబ్బంది అనుమతులకు మీ స్వంత యాక్సెస్ తొలగించబడుతుంది.", + "selfAccessWarningStaffPrivileged": "దీన్ని సేవ్ చేయడం వల్ల యజమాని మరియు మేనేజర్ ఖాతాలకు మీ స్వంత యాక్సెస్ తొలగించబడుతుంది.", + "selfAccessWarningStaffOperational": "దీన్ని సేవ్ చేయడం వల్ల సిబ్బంది ఖాతాలకు మీ స్వంత యాక్సెస్ తొలగించబడుతుంది.", + "selfAccessWarningSettings": "దీన్ని సేవ్ చేయడం వల్ల స్టోర్ సెట్టింగ్లకు మీ స్వంత యాక్సెస్ తొలగించబడుతుంది.", + "administrationUnreachable": "ఈ మార్పు వల్ల సిబ్బంది, అనుమతులు లేదా స్టోర్ సెట్టింగ్లను నిర్వహించడానికి ఏ ఖాతా లేకుండా పోతుంది. మొదట మరో యాక్టివ్ యజమానికి ఈ అనుమతులను ఇవ్వండి.", + "selfPrivilegeChangeTitle": "మీ స్వంత యాక్సెస్కు ఈ మార్పును నిర్ధారించండి", + "selfPrivilegeChangePrompt": "ఈ మార్పు సిబ్బంది, అనుమతులు లేదా స్టోర్ సెట్టింగ్లకు మీ స్వంత యాక్సెస్ను మారుస్తుంది. కొనసాగించడానికి మీ పిన్ నమోదు చేయండి, లేదా ఈ మార్పు చేయమని మరో యజమానిని అడగండి.", + "selfPrivilegeNotConfirmed": "మీ స్వంత యాక్సెస్కు చేసిన ఈ మార్పు నిర్ధారించబడలేదు, కాబట్టి ఏదీ సేవ్ కాలేదు. మీ ఖాతా కోసం పిన్ సెట్ చేయండి, లేదా ఈ మార్పు చేయమని మరో యజమానిని అడగండి.", + "editorFooterNote": "ఆమోద పిన్లు, చివరి యాక్టివ్ యజమాని, రీఫండ్ సమయ పరిమితులు మరియు కిచెన్ స్టేషన్ కేటాయింపుల వంటి సున్నితమైన వ్యాపార నియమాలు ఇప్పటికీ వర్తిస్తాయి." + }, + "permissionAudit": { + "title": "అనుమతి మార్పుల చరిత్ర", + "subtitle": "పైన ఉన్న పాత్ర అనుమతుల నుండి చేసిన ప్రతి మార్పు, ఇటీవలివి మొదట.", + "columnTime": "సమయం", + "columnActor": "చేసినవారు", + "columnTarget": "లక్ష్యం", + "columnPermission": "అనుమతి", + "columnChange": "మార్పు", + "targetTypeRole": "పాత్ర", + "targetTypeUser": "సిబ్బంది", + "empty": "ఇంకా అనుమతి మార్పులు లేవు.", + "loadMore": "మరిన్ని లోడ్ చేయి" + }, + "support": { + "askAi": "AI ని అడగండి", + "askAiCopied": "{provider} కోసం లోపం కాపీ చేయబడింది — ఇప్పుడే తెరుచుకున్న చాట్లో దాన్ని పేస్ట్ చేయండి.", + "askAiCopyFailed": "స్వయంచాలకంగా కాపీ చేయడం సాధ్యం కాలేదు — పైన ఉన్న లోపాన్ని కాపీ చేసి {provider} లో పేస్ట్ చేయండి.", + "attachLog": "లాగ్ ఫైల్ జోడించు", + "attachLogHint": "ఈ పరికరం నుండి ఆర్డర్ వివరాలు, కస్టమర్ పేర్లు లేదా ఇతర ఆన్-స్క్రీన్ కార్యకలాపాలు ఉండవచ్చు — దాన్ని మినహాయించడానికి అన్చెక్ చేయండి.", + "category": "సమస్య రకం", + "categoryAccount": "ఖాతా లేదా క్లౌడ్", + "categoryBug": "బగ్ నివేదిక", + "categoryFeature": "ఫీచర్ అభ్యర్థన", + "categoryGeneral": "సాధారణ సహాయం", + "categoryPrinter": "ప్రింటర్ సమస్య", + "categoryTax": "పన్ను కాన్ఫిగరేషన్", + "confirmingDelivery": "సపోర్ట్ సర్వర్తో నిర్ధారిస్తోంది…", + "contactDetails": "సంప్రదింపు వివరాలు", + "contactHint": "సపోర్ట్ మీకు సమాధానం ఇవ్వడానికి FloCafe ఈ వివరాలను పంపుతుంది.", + "contactName": "సంప్రదింపు పేరు", + "describeIssue": "సమస్యను వివరించండి", + "description": "వివరమైన వివరణ", + "descriptionHint": "మరిన్ని వివరాలు సమస్యను వేగంగా అర్థం చేసుకుని పరిష్కరించడానికి మాకు సహాయపడతాయి.", + "descriptionPlaceholder": "ఏం జరిగింది? మీరు ఏమి చేయడానికి ప్రయత్నిస్తున్నారు? మీరు ఏమి ఆశించారు? ఏదైనా లోప సందేశం మరియు సమస్యను మళ్లీ చూపే దశలను చేర్చండి.", + "diagnosticsCreateTicket": "టికెట్ సృష్టించు", + "diagnosticsFailureReport": "ఈ పరికరంలో ఒక సమస్య నమోదు చేయబడింది. దిగువ వివరాలు స్వయంచాలకంగా సేకరించబడ్డాయి.", + "dialogTitle": "సపోర్ట్ టికెట్ సమర్పించండి", + "dismiss": "విస్మరించు", + "email": "ఈమెయిల్", + "getHelp": "సహాయం పొందండి", + "location": "స్థానం", + "menuLabel": "మద్దతు", + "menuSubmitTicket": "టికెట్ సమర్పించు", + "menuWhatsapp": "WhatsApp కమ్యూనిటీ", + "phone": "ఫోన్", + "platform": "ప్లాట్ఫారమ్", + "privacyHint": "కస్టమర్ పేర్లు, ఫోన్ నంబర్లు, ఆర్డర్ వివరాలు, పాస్వర్డ్లు లేదా API కీలు స్వయంచాలకంగా చేర్చబడవు.", + "profileLoadFailed": "మీ సపోర్ట్ సంప్రదింపు వివరాలను లోడ్ చేయడం సాధ్యం కాలేదు", + "queued": "మీ అభ్యర్థన క్యూలో ఉంచబడింది మరియు FloCafe ఆన్లైన్లోకి వచ్చినప్పుడు పంపబడుతుంది.", + "requestId": "అభ్యర్థన ఐడి", + "requestQueued": "మీ సపోర్ట్ అభ్యర్థన క్యూలో ఉంచబడింది", + "restaurant": "రెస్టారెంట్", + "showPayload": "ఖచ్చితంగా ఏమి పంపబడుతుందో చూపించు", + "stillQueuedLocally": "ఇంకా ఈ పరికరంలో క్యూలో ఉంది — తిరిగి ఆన్లైన్లోకి వచ్చినప్పుడు ఇది స్వయంచాలకంగా మళ్లీ ప్రయత్నిస్తుంది.", + "subject": "విషయం", + "subjectPlaceholder": "సమస్య యొక్క సంక్షిప్త సారాంశం", + "submit": "సపోర్ట్ అభ్యర్థన పంపు", + "submitFailed": "సపోర్ట్ అభ్యర్థనను క్యూలో ఉంచడం సాధ్యం కాలేదు", + "submitting": "అభ్యర్థనను క్యూలో ఉంచుతోంది…", + "subtitle": "బగ్ నివేదించండి, ప్రశ్న అడగండి, ఫీచర్ కోరండి, లేదా ఏమి పనిచేయడం లేదో మాకు చెప్పండి.", + "supportCode": "సపోర్ట్ కోడ్", + "supportCodeHint": "ఈ అభ్యర్థన గురించి మీరు సపోర్ట్ను సంప్రదిస్తే దీన్ని పేర్కొనండి.", + "tabDiagnostics": "డయాగ్నస్టిక్స్ & లాగ్లు", + "technicalDetails": "సాంకేతిక వివరాలు చేర్చబడ్డాయి", + "technicalHint": "సురక్షితమైన యాప్ మరియు పరికర వివరాలు స్వయంచాలకంగా జోడించబడతాయి.", + "title": "సహాయం & మద్దతు", + "urgency": "అత్యవసర స్థాయి", + "urgencyHigh": "అధికం — పెద్ద అంతరాయం", + "urgencyLow": "తక్కువ — ప్రశ్న లేదా అభిప్రాయం", + "urgencyNormal": "సాధారణం — పని ప్రభావితమైంది", + "urgencyUrgent": "అత్యవసరం — పనిచేయలేని స్థితి", + "version": "వెర్షన్" + }, + "tables": { + "allFloors": "అన్ని ఫ్లోర్లు", + "add": "టేబుల్ జోడించు", + "addTable": "టేబుల్ జోడించు", + "cancel": "రద్దు", + "capacity": "సామర్థ్యం", + "capacitySeats": "సీట్లు: {count}", + "create": "సృష్టించు", + "createTable": "టేబుల్ సృష్టించు", + "creating": "సృష్టిస్తోంది...", + "deactivate": "డీయాక్టివేట్ చేయి", + "floor": "ఫ్లోర్", + "floorFilter": "ఫ్లోర్ వారీగా టేబుళ్లను ఫిల్టర్ చేయి", + "editTable": "టేబుల్ సవరించు", + "editTableHelp": "టేబుల్ పేరు, సీట్లు, ఫ్లోర్ లేదా విభాగాన్ని అప్డేట్ చేయండి.", + "linkCustomer": "కస్టమర్ను లింక్ చేయి (ఐచ్ఛికం)", + "loadFailed": "టేబుళ్లను లోడ్ చేయడం విఫలమైంది", + "markAvailable": "అందుబాటులో ఉన్నట్లు గుర్తించు", + "newCustomer": "కొత్త కస్టమర్", + "noActiveOrders": "యాక్టివ్ ఆర్డర్లు లేవు", + "noTablesYet": "ఇంకా టేబుళ్లు లేవు. మీ మొదటి టేబుల్ జోడించండి!", + "phoneDigitsExact": "ఫోన్ నంబర్ ఖచ్చితంగా {count} అంకెలు ఉండాలి", + "reactivate": "రీయాక్టివేట్ చేయి", + "reserve": "రిజర్వ్ చేయి", + "reserveTable": "టేబుల్ రిజర్వ్ చేయి", + "reservedFor": "టేబుల్ {name} {customer} కోసం రిజర్వ్ చేయబడింది", + "reservedNoCustomer": "టేబుల్ {name} రిజర్వ్ చేయబడింది", + "reserving": "రిజర్వ్ చేస్తోంది...", + "saveChanges": "మార్పులను సేవ్ చేయి", + "section": "విభాగం", + "searchCustomerPlaceholder": "ఫోన్ లేదా పేరు ద్వారా వెతకండి...", + "showOrderDetails": "ఆర్డర్ వివరాలు చూపించు", + "statusAvailable": "అందుబాటులో ఉంది", + "statusCleaning": "శుభ్రపరుస్తోంది", + "statusHeld": "హోల్డ్ చేయబడింది", + "statusOccupied": "ఆక్రమించబడింది", + "statusReserved": "రిజర్వ్ చేయబడింది", + "tableCreateFailed": "టేబుల్ సృష్టించడం విఫలమైంది", + "tableCapacityInvalid": "సామర్థ్యం ధనాత్మక పూర్ణ సంఖ్య అయి ఉండాలి", + "tableInactiveDuplicate": "ఆ టేబుల్ ఇప్పటికే ఉంది కానీ డీయాక్టివేట్ చేయబడింది. జాబితా నుండి దాన్ని రీయాక్టివేట్ చేయండి.", + "tableLocationInvalid": "ఫ్లోర్ మరియు విభాగం టెక్స్ట్ విలువలై ఉండాలి", + "tableNameDuplicate": "ఆ పేరుతో టేబుల్ ఇప్పటికే ఉంది", + "tableNameRequired": "టేబుల్ పేరు నమోదు చేయండి", + "tableCreated": "టేబుల్ సృష్టించబడింది", + "tableUpdated": "టేబుల్ అప్డేట్ చేయబడింది", + "tableName": "పేరు", + "tableNamePlaceholder": "ఉదా., T1, టేబుల్ 1", + "tableReserveFailed": "టేబుల్ రిజర్వ్ చేయడం విఫలమైంది", + "tableUpdateFailed": "అప్డేట్ చేయడం విఫలమైంది", + "title": "టేబుళ్లు", + "updateStatusFailed": "అప్డేట్ చేయడం విఫలమైంది", + "floorplanUnassigned": "కేటాయించనివి", + "floorplanUnassignedHint": "ఫ్లోర్ కేటాయించని టేబుళ్లు. కొత్తది సృష్టించడానికి + ఫ్లోర్ జోడించు క్లిక్ చేయండి.", + "floorplanAuto": "ఆటో", + "floorplanAutoHint": "ఉంచిన టేబుళ్లకు మాత్రమే సరిపోయేలా కాన్వాస్ను కుదించండి — చిన్న లేఅవుట్ల కోసం తక్కువ ఖాళీ స్థలం.", + "floorplanCustomHint": "కాన్వాస్ను మీ రెస్టారెంట్ వాస్తవ కొలతలకు (మీటర్లలో) సెట్ చేయండి. టేబుళ్లు అదే శాతం స్థానాలలో ఉంటాయి, కాబట్టి 50% వద్ద టేబుల్ ఉన్న 10×6 మీ గదిలో టేబుల్ గది మధ్యలో ఉంటుంది.", + "floorplanCustomLockedHint": "కాన్వాస్ పరిమాణాన్ని మార్చడానికి లేఅవుట్ సవరించుకు మారండి.", + "floorplanCanvasSize": "కాన్వాస్ పరిమాణం", + "floorplanCanvasWidth": "కాన్వాస్ వెడల్పు", + "floorplanCanvasHeight": "కాన్వాస్ ఎత్తు", + "floorplanHint": "మ్యాప్పై టేబుళ్లను ఉంచడానికి వాటిని లాగి, ఆపై సేవ్ చేయండి. టేబుల్ పేరు మరియు సీట్లను సవరించడానికి దానిపై క్లిక్ చేయండి.", + "floorplanSaved": "ఫ్లోర్ ప్లాన్ సేవ్ చేయబడింది", + "floorplanSaveFailed": "ఫ్లోర్ ప్లాన్ సేవ్ చేయడం విఫలమైంది", + "floorplanUnplaced": "ఉంచని టేబుళ్లు", + "floorplanEmptyCanvas": "దిగువ ట్రే నుండి టేబుళ్లను మ్యాప్పైకి లాగండి.", + "floorplanAriaHint": "తరలించడానికి లాగండి లేదా బాణం కీలను ఉపయోగించండి; సవరించడానికి Enter నొక్కండి; వేగంగా తరలించడానికి Shift పట్టుకోండి.", + "floorplanEditHint": "సవరించడానికి క్లిక్ చేయండి, తరలించడానికి లాగండి.", + "addFloor": "ఫ్లోర్ జోడించు", + "newFloor": "కొత్త ఫ్లోర్", + "floorName": "ఫ్లోర్ పేరు", + "floorplanAllFloors": "అన్ని ఫ్లోర్లు", + "viewOrder": "ఆర్డర్ చూడండి", + "markCleaning": "శుభ్రపరచాల్సినదిగా గుర్తించు", + "floorplanViewPlan": "ఫ్లోర్ ప్లాన్", + "floorplanViewList": "జాబితా", + "editLayout": "లేఅవుట్ సవరించు", + "backToPlan": "ఫ్లోర్ ప్లాన్కు తిరిగి వెళ్ళు", + "floorActions": "ఫ్లోర్ చర్యలు", + "renameFloor": "ఫ్లోర్ పేరు మార్చు", + "deleteFloor": "ఫ్లోర్ తొలగించు", + "renameFloorTitle": "ఫ్లోర్ {name} పేరు మార్చు", + "renameFloorConfirm": "ఫ్లోర్ పేరు మార్చు", + "renameFloorMergeHint": "{target} పేరుతో ఫ్లోర్ ఇప్పటికే ఉంది. రెండు ఫ్లోర్లలోని టేబుళ్లు విలీనం చేయబడతాయి.", + "renameFloorHint": "టేబుళ్లు ఉన్న చోటే ఉంటాయి. ఇప్పటికే ఉన్న ఫ్లోర్ పేరుకు మార్చడం వల్ల అవి విలీనం అవుతాయి.", + "deleteFloorTitle": "ఫ్లోర్ {name} తొలగించాలా?", + "deleteFloorHint": "ఈ ఫ్లోర్లోని {count, plural, one {# టేబుల్} other {# టేబుళ్లు}} కేటాయించనివికి మారతాయి. టేబుళ్లు మాత్రం అలాగే ఉంటాయి.", + "deleteFloorConfirm": "ఫ్లోర్ తొలగించు", + "floorRenamed": "ఫ్లోర్ పేరు మార్చబడింది", + "floorRenameFailed": "ఫ్లోర్ పేరు మార్చడం విఫలమైంది", + "floorDeleted": "ఫ్లోర్ తొలగించబడింది", + "floorDeleteFailed": "ఫ్లోర్ తొలగించడం విఫలమైంది", + "confirmMoveOrder": "{table} కు తరలించు", + "moveOrder": "ఆర్డర్ తరలించు", + "moveOrderDescription": "యాక్టివ్ ఆర్డర్ను {from} నుండి మరో టేబుల్కు బదిలీ చేయండి.", + "moveTable": "టేబుల్ తరలించు", + "selectDestinationTable": "గమ్యస్థాన టేబుల్ ఎంచుకోండి", + "tableMovedSuccess": "ఆర్డర్ {from} నుండి {to} కు తరలించబడింది", + "tableMoveFailed": "టేబుల్ ఆర్డర్ తరలించడం విఫలమైంది", + "targetTableOccupied": "గమ్యస్థాన టేబుల్లో ఇప్పటికే యాక్టివ్ ఆర్డర్ ఉంది" + }, + "tax": { + "actionActivate": "ప్యాక్ యాక్టివేట్ చేయబడింది", + "actionCreateOverride": "ఓవర్రైడ్ జోడించబడింది", + "actionInstallBundled": "బండిల్ చేసిన ప్యాక్ ఇన్స్టాల్ చేయబడింది", + "actionInstallDownloaded": "డౌన్లోడ్ చేసిన ప్యాక్ ఇన్స్టాల్ చేయబడింది", + "actionResetOverride": "ఓవర్రైడ్ తీసివేయబడింది", + "actionRollback": "ప్యాక్ వెనక్కి మళ్లించబడింది", + "actionUpdateOverride": "ఓవర్రైడ్ సవరించబడింది", + "actions": "చర్యలు", + "active": "యాక్టివ్", + "activeVersion": "యాక్టివ్ వెర్షన్", + "addCategory": "వర్గం జోడించు", + "addComponent": "భాగం జోడించు", + "addOverride": "ఓవర్రైడ్ జోడించు", + "advancedTools": "అధునాతన పన్ను టూల్స్", + "advancedToolsHint": "ఐచ్ఛిక పరీక్ష, ఛార్జీ నియమాలు, మినహాయింపులు, ప్యాక్ వివరాలు మరియు ఆడిట్ చరిత్ర. చాలా స్టోర్లకు ఇవి ఎప్పుడూ అవసరం ఉండదు.", + "amount": "మొత్తం", + "askOwnerToInstall": "ఈ అప్డేట్ ఇన్స్టాల్ చేయమని యజమానిని అడగండి.", + "auditActivatePack": "మునుపటి వెర్షన్: {previousVersionId}", + "auditCreateOverride": "{entityType} {entityId} → {categoryId}", + "auditHistory": "ఆడిట్ చరిత్ర", + "auditInstallBundled": "అప్లికేషన్ బండిల్ నుండి వెర్షన్ {version}", + "auditInstallDownloaded": "GitHub Releases నుండి వెర్షన్ {version} ధృవీకరించబడి ఇన్స్టాల్ చేయబడింది", + "auditResetOverride": "{entityType} {entityId} అధికారిక విధానానికి రీసెట్ చేయబడింది", + "auditRollbackPack": "{previousVersionId} నుండి వెనక్కి మళ్లించబడింది", + "auditSystem": "సిస్టమ్", + "auditUnknownUser": "తెలియని వినియోగదారు", + "auditUpdateOverride": "{entityType} {entityId}: {before} → {after}", + "behaviorCountryDefault": "దేశ డిఫాల్ట్", + "behaviorExclusive": "పన్ను అదనం", + "behaviorExempt": "మినహాయింపు", + "behaviorInclusive": "పన్ను కలిపి", + "calculate": "లెక్కించు", + "calculateFailed": "పన్ను లెక్కించడం సాధ్యం కాలేదు", + "cancel": "రద్దు", + "category": "వర్గం", + "categoryNamePlaceholder": "వర్గం పేరు, ఉదా. స్టాండర్డ్", + "categoryNameRequired": "ప్రతి పన్ను వర్గానికి పేరు ఉండాలి", + "categoryNeedsComponent": "\"{label}\" కు కనీసం ఒక పన్ను భాగం ఉండాలి", + "chargeCategories": "ఛార్జీ పన్ను వర్గాలు", + "chargeCategoriesHint": "ప్రతి ఆర్డర్-స్థాయి ఛార్జీ కోసం ఉపయోగించే వర్గాన్ని ఎంచుకోండి. కాన్ఫిగర్ చేయని ఛార్జీలు పాత విధానాన్ని కొనసాగిస్తాయి మరియు పన్ను లేకుండా ఉంటాయి.", + "chargeCategoriesNotActive": "ఛార్జీ వర్గాలను మార్చడానికి యాక్టివ్ స్టోర్-దేశ ప్యాక్ను ఎంచుకోండి.", + "chargeNotConfigured": "కాన్ఫిగర్ చేయలేదు · పాత విధానం", + "chargeRestored": "{entity} పాత విధానానికి పునరుద్ధరించబడింది", + "chargeSaveFailed": "ఛార్జీ పన్ను వర్గాన్ని సేవ్ చేయడం సాధ్యం కాలేదు", + "chargeSaved": "{entity} పన్ను వర్గం సేవ్ చేయబడింది", + "checkUpdates": "అప్డేట్ల కోసం తనిఖీ చేయి", + "checkUpdatesFailed": "పన్ను ప్లగిన్ అప్డేట్ల కోసం తనిఖీ చేయడం సాధ్యం కాలేదు", + "checking": "తనిఖీ చేస్తోంది…", + "checksFailed": "యాక్టివేషన్ తనిఖీలు విఫలమయ్యాయి", + "checksPassed": "{total} యాక్టివేషన్ తనిఖీలలో {passed} పూర్తయ్యాయి", + "chooseEntity": "{entity} ఎంచుకోండి", + "chooseTargetAndCategory": "లక్ష్యం మరియు పన్ను వర్గం రెండింటినీ ఎంచుకోండి", + "communityPackDisclaimer": "ఈ {country} పన్ను ప్యాక్ (v{version}) బహిరంగంగా అందుబాటులో ఉన్న సమాచారం నుండి సంకలనం చేయబడింది మరియు వృత్తిపరంగా సమీక్షించబడలేదు. రేట్లు మరియు నియమాలు అసంపూర్ణంగా లేదా పాతవిగా ఉండవచ్చు. దీని వినియోగం వల్ల కలిగే తప్పు పన్ను లెక్కలు లేదా ఫైలింగ్లకు FloCafe మరియు దాని సహాయకులు ఎటువంటి బాధ్యత వహించరు — చట్టపరమైన సమ్మతి కోసం దీనిపై ఆధారపడే ముందు స్థానిక పన్ను నిపుణుడితో రేట్లను ధృవీకరించండి, మరియు ఏదైనా సమస్యను వెంటనే నివేదించండి. ఈ ప్యాక్ను యాక్టివేట్ చేయాలా?", + "componentNeedsValidRate": "\"{label}\" కు చెల్లబాటు అయ్యే రేటు అవసరం", + "componentPlaceholder": "ఉదా. పన్ను 1", + "createManual": "మాన్యువల్ పన్ను కాన్ఫిగరేషన్ సృష్టించు", + "currentVersion": "(ప్రస్తుత v{current})", + "defaultBehavior": "డిఫాల్ట్ విధానం", + "defaultCategory": "డిఫాల్ట్ వర్గం", + "defaultCategoryHint": "ఉత్పత్తుల పేజీలో వ్యక్తిగత ఉత్పత్తులను ఇప్పటికీ మార్చవచ్చు. యాడ్-ఆన్లు ఎల్లప్పుడూ వాటి ఐటెమ్ వర్గాన్ని అనుసరిస్తాయి — అవి ఐటెమ్లో భాగంగా పన్ను విధించబడతాయి, విడిగా ఎప్పుడూ కాదు.", + "defaultDelivery": "డెలివరీ ఛార్జీలు", + "defaultNewProducts": "కొత్త ఉత్పత్తులు", + "defaultPackaging": "ప్యాకేజింగ్ ఛార్జీలు", + "defaultServiceCharge": "సర్వీస్ ఛార్జీలు", + "dependsOn": "దీనిపై ఆధారపడి ఉంటుంది", + "edit": "సవరించు", + "effectiveFrom": "అమలు తేదీ {date}", + "enableFailed": "ఈ దేశం కోసం పన్నులను ఆన్ చేయడం సాధ్యం కాలేదు", + "enabledFor": "{country} కోసం పన్నులు ఆన్ చేయబడ్డాయి", + "enabling": "ఆన్ చేస్తోంది…", + "entityAddon": "యాడ్-ఆన్", + "entityDelivery": "డెలివరీ ఛార్జ్", + "entityPackaging": "ప్యాకేజింగ్ ఛార్జ్", + "entityProduct": "ఉత్పత్తి", + "entityServiceCharge": "సర్వీస్ ఛార్జ్", + "exclusiveLabel": "పన్ను-అదనం (మెనూ ధరపై అదనంగా జోడించబడుతుంది)", + "fixed": "స్థిరమైనది", + "hide": "దాచు", + "inclusiveLabel": "పన్ను-కలిపి (ఇప్పటికే మెనూ ధరలో కలిపి ఉంటుంది)", + "installAndActivate": "ఇన్స్టాల్ & యాక్టివేట్ చేయి", + "installUpdateFailed": "పన్ను ప్లగిన్ అప్డేట్ ఇన్స్టాల్ చేయడం సాధ్యం కాలేదు", + "installedPacks": "ఇన్స్టాల్ చేసిన దేశ ప్యాక్లు", + "installedPacksHint": "FloCafe {country} కోసం ప్లగిన్ను స్వయంచాలకంగా ఎంచుకుంటుంది.", + "installedVersions": "ఇన్స్టాల్ చేసిన వెర్షన్లు", + "installing": "ఇన్స్టాల్ చేస్తోంది…", + "invalidTestAmount": "దయచేసి చెల్లబాటు అయ్యే ధనాత్మక పరీక్ష లెక్కింపు మొత్తాన్ని నమోదు చేయండి", + "jurisdiction": "అధికార పరిధి", + "loadFailed": "పన్ను కాన్ఫిగరేషన్ లోడ్ చేయడం సాధ్యం కాలేదు", + "loadPackDetailsFailed": "పన్ను ప్యాక్ వివరాలను లోడ్ చేయడం సాధ్యం కాలేదు", + "loading": "పన్ను కాన్ఫిగరేషన్ లోడ్ అవుతోంది…", + "managerNotice": "మేనేజర్లు ప్యాక్లు, ఓవర్రైడ్లు, ఆడిట్ చరిత్రను సమీక్షించగలరు మరియు పరీక్ష లెక్కలను రన్ చేయగలరు. యజమానులు మాత్రమే మార్పులు చేయగలరు.", + "manualBuilder": "మాన్యువల్ పన్ను బిల్డర్", + "manualBuilderHint": "{country} కోసం మీ స్వంత పన్ను వర్గాలను నిర్వచించండి. ప్రతి వర్గంలో ఒకటి కంటే ఎక్కువ పేరున్న రేట్లు ఉండవచ్చు — ఉదాహరణకు పన్ను 1 2.5% + పన్ను 2 2.5% తో \"స్టాండర్డ్\" వర్గం. మీ దేశానికి ఇంకా అధికారిక పన్ను ప్యాక్ లేకపోతే, లేదా దాన్ని మీ స్వంత రేట్లతో భర్తీ చేయడానికి దీన్ని ఉపయోగించండి.", + "manualOverrideConfirm": "{country} కోసం ఇప్పటికే అధికారిక పన్ను ప్యాక్ యాక్టివ్గా ఉంది. సేవ్ చేయడం వల్ల అది ఈ మాన్యువల్ కాన్ఫిగరేషన్తో భర్తీ చేయబడుతుంది.", + "manualSaveFailed": "మాన్యువల్ పన్ను కాన్ఫిగరేషన్ సేవ్ చేయడం సాధ్యం కాలేదు", + "manualSaved": "మాన్యువల్ పన్ను కాన్ఫిగరేషన్ సేవ్ చేయబడింది మరియు యాక్టివేట్ చేయబడింది", + "menuPrices": "మెనూ ధరలు", + "merchantOverrides": "వ్యాపారి ఓవర్రైడ్లు", + "merchantOverridesHint": "ఉత్పత్తి మరియు వర్గ కేటాయింపుల కంటే ఓవర్రైడ్లకు ప్రాధాన్యత ఉంటుంది, కానీ లావాదేవీ మినహాయింపులే గెలుస్తాయి.", + "mode": "పన్ను మోడ్", + "modeManual": "మాన్యువల్ పన్ను రేట్లు", + "modeManualHint": "{country} కోసం FloCafe మీ మాన్యువల్ పన్ను కాన్ఫిగరేషన్ను ఉపయోగిస్తోంది.", + "modeManualUnsavedHint": " ఇంకా సేవ్ చేయలేదు — దిగువన మీ రేట్లను కాన్ఫిగర్ చేసి, యాక్టివేట్ చేయడానికి సేవ్ చేయండి.", + "modeOff": "పన్ను ఆఫ్ చేయి", + "modeOffHint": "FloCafe సాధారణ పన్ను-లేని ప్రొఫైల్ను ఉపయోగిస్తోంది. పన్ను లెక్కించబడదు లేదా ప్రింట్ చేయబడదు.", + "modeOfficial": "అధికారిక పన్ను ప్యాక్", + "modeOfficialHint": "{country} కోసం FloCafe ధృవీకరించిన ప్లగిన్ను ఉపయోగిస్తోంది.", + "noActivePack": "యాక్టివ్గా ఉన్న ఇన్స్టాల్ చేసిన ప్యాక్ ఏదీ అందుబాటులో లేదు.", + "noActiveVersion": "ఈ ప్యాక్కు ఇంకా యాక్టివ్ వెర్షన్ లేదు — దిగువన ఇన్స్టాల్ చేసిన వెర్షన్ను యాక్టివేట్ చేయండి.", + "noAudit": "పన్ను కాన్ఫిగరేషన్ మార్పులు ఏవీ నమోదు కాలేదు.", + "noOfficialPack": "{country} కోసం అధికారిక పన్ను ప్యాక్ కనుగొనబడలేదు", + "noOverrides": "వ్యాపారి ఓవర్రైడ్లు లేవు. అధికారిక ప్యాక్ విధానం అమలులో ఉంది.", + "noPluginToCheck": "అప్డేట్ల కోసం తనిఖీ చేయడానికి ఇన్స్టాల్ చేసిన పన్ను ప్లగిన్ ఏదీ లేదు", + "none": "ఏదీ లేదు", + "overrideAdded": "పన్ను ఓవర్రైడ్ జోడించబడింది", + "overrideRemoveFailed": "పన్ను ఓవర్రైడ్ తీసివేయడం సాధ్యం కాలేదు", + "overrideRemoved": "పన్ను ఓవర్రైడ్ తీసివేయబడింది; అధికారిక ప్యాక్ విధానం పునరుద్ధరించబడింది", + "overrideSaveFailed": "పన్ను ఓవర్రైడ్ సేవ్ చేయడం సాధ్యం కాలేదు", + "overrideUpdated": "పన్ను ఓవర్రైడ్ అప్డేట్ చేయబడింది", + "packDefault": "ప్యాక్ డిఫాల్ట్", + "packNotActive": "ఈ ఇన్స్టాల్ చేసిన ప్యాక్ ప్రస్తుత స్టోర్ కోసం యాక్టివ్గా లేదు. పరీక్షించడానికి యాక్టివ్ ప్యాక్ను ఎంచుకోండి.", + "packReference": "ప్యాక్ రిఫరెన్స్", + "packReferenceHint": "యాక్టివ్గా ఇన్స్టాల్ చేసిన JSON ప్యాక్ నుండి రీడ్-ఓన్లీ వర్గాలు మరియు నియమాలు.", + "payableTotal": "చెల్లించాల్సిన మొత్తం", + "pluginVersion": "పన్ను ప్లగిన్ వెర్షన్", + "publishedAt": "ప్రచురించినది {date}", + "readOnly": "రీడ్ ఓన్లీ", + "reassignedSummary": "{summary} తమ మునుపటి పన్ను వర్గాన్ని కోల్పోయి కొత్త డిఫాల్ట్కు తిరిగి కేటాయించబడ్డాయి.", + "refresh": "రిఫ్రెష్", + "reinstallConfirm": "ఈ పన్ను ప్లగిన్ను మళ్లీ డౌన్లోడ్ చేసి దాని వర్గాలు, నియమాలు మరియు బిల్లింగ్ టెంప్లేట్ను మళ్లీ నిర్మించాలా? ఇది ఇన్స్టాల్ చేసిన వెర్షన్ను మార్చదు.", + "reinstallFailed": "పన్ను ప్లగిన్ను మళ్లీ ఇన్స్టాల్ చేయడం సాధ్యం కాలేదు", + "reinstallHint": "ఈ ప్లగిన్ను మళ్లీ డౌన్లోడ్ చేసి దాని వర్గాలు, నియమాలు మరియు బిల్లింగ్ టెంప్లేట్ను మళ్లీ నిర్మించండి", + "reinstallPlugin": "ప్లగిన్ మళ్లీ ఇన్స్టాల్ చేయి", + "reinstalled": "పన్ను ప్లగిన్ మళ్లీ ఇన్స్టాల్ చేయబడింది — దాని బిల్లింగ్ టెంప్లేట్ ఇప్పుడు ప్రింటర్లు > బిల్లు టెంప్లేట్ క్రింద కనిపించాలి", + "reinstalling": "మళ్లీ ఇన్స్టాల్ చేస్తోంది…", + "remove": "తీసివేయి", + "removeCategory": "వర్గాన్ని తీసివేయి", + "removeComponent": "భాగాన్ని తీసివేయి", + "removeOverrideConfirm": "{target} కోసం ఓవర్రైడ్ను తీసివేయాలా?", + "replace": "భర్తీ చేయి", + "reportIssue": "ఈ పన్ను ప్యాక్తో సమస్యను నివేదించండి", + "reportIssueFailed": "నివేదికను పంపడం సాధ్యం కాలేదు — దయచేసి మళ్లీ ప్రయత్నించండి", + "reportIssueSent": "ధన్యవాదాలు — సమస్య నివేదించబడింది", + "requestQueued": " మీ అభ్యర్థన బృందం కోసం క్యూలో ఉంచబడింది.", + "rule": "నియమం", + "rules": "నియమాలు", + "saveManual": "మాన్యువల్ పన్ను కాన్ఫిగరేషన్ సేవ్ చేయి", + "saveOverride": "ఓవర్రైడ్ సేవ్ చేయి", + "saving": "సేవ్ అవుతోంది…", + "scope": "పరిధి", + "selectActivePack": "చెకౌట్ లెక్కింపును రన్ చేయడానికి యాక్టివ్ స్టోర్-దేశ ప్యాక్ను ఎంచుకోండి", + "storeCountry": "స్టోర్ దేశం", + "storeWide": "స్టోర్-వ్యాప్తంగా", + "storeWideCharge": "స్టోర్-వ్యాప్త ఛార్జీ", + "subtitle": "మీ స్టోర్ దేశం కోసం ధృవీకరించిన పన్ను నియమాలను ఆన్ చేయండి. FloCafe ప్రామాణిక ఉత్పత్తి పన్ను గ్రూప్ను స్వయంచాలకంగా వర్తింపజేస్తుంది; ప్రతి ఉత్పత్తికి మినహాయింపులను మార్చవచ్చు.", + "supportUnavailable": "{country} కోసం పన్ను మద్దతు ఇంకా అందుబాటులో లేదు. మేము FloCafe బృందం నుండి ప్లగిన్ను అభ్యర్థించాము మరియు త్వరలో దాన్ని నిర్మిస్తాము. అది సిద్ధమయ్యే వరకు పన్నులు ఆఫ్లో ఉంటాయి.", + "target": "లక్ష్యం", + "taxableBase": "పన్ను విధించదగిన మొత్తం", + "testCalculation": "పరీక్ష లెక్కింపు", + "testCalculationHint": "యాక్టివ్ ప్యాక్ మరియు చెకౌట్ ఉపయోగించే అదే పన్ను ఇంజిన్ను ఉపయోగిస్తుంది. ఇది లావాదేవీని సేవ్ చేయదు.", + "title": "పన్ను కాన్ఫిగరేషన్", + "trustStatus": "విశ్వసనీయ స్థితి", + "turnOffFailed": "పన్నులను ఆఫ్ చేయడం సాధ్యం కాలేదు", + "turnedOff": "పన్నులు ఆఫ్ చేయబడ్డాయి", + "type": "రకం", + "untitledCategory": "పేరులేని వర్గం", + "upToDate": "పన్ను ప్లగిన్ తాజాగా ఉంది", + "updateAvailable": "అప్డేట్ అందుబాటులో ఉంది: v{version}", + "updateAvailableLabel": "ప్లగిన్ అప్డేట్ అందుబాటులో ఉంది:", + "updated": "అప్డేట్ చేయబడింది", + "updatedTo": "పన్ను ప్లగిన్ v{version} కు అప్డేట్ చేయబడింది", + "value": "విలువ", + "yourStore": "మీ స్టోర్", + "tax": "పన్ను" + }, + "update": { + "currentVersion": "ప్రస్తుత వెర్షన్: {version}", + "downloadingBadge": "↓ {percent}%", + "downloadingDetail": "వెర్షన్ {version} డౌన్లోడ్ అవుతోంది...", + "readyBadge": "అప్డేట్ సిద్ధంగా ఉంది", + "restartNow": "ఇప్పుడే రీస్టార్ట్ చేయి", + "sectionLabel": "యాప్ అప్డేట్", + "versionReady": "వెర్షన్ {version} ఇన్స్టాల్ చేయడానికి సిద్ధంగా ఉంది", + "installGuardTitle": "అప్డేట్ ఇన్స్టాల్ చేయడానికి రీస్టార్ట్ చేయాలా?", + "installGuardDescription": "యాప్ రీస్టార్ట్ అయ్యే ముందు దీనికి మేనేజర్ లేదా యజమాని ఆమోదం అవసరం.", + "installWarnTitle": "హెచ్చరిక: అప్డేట్ సమయంలో అన్నీ ఆఫ్లైన్లోకి వెళ్తాయి", + "installWarnSystemsDown": "అప్డేట్ ఇన్స్టాల్ అయ్యే సమయంలో అన్ని సిస్టమ్లు (POS, KDS, ప్రింటింగ్, నివేదికలు) ఆగిపోతాయి.", + "installWarnAutoRestart": "కొత్త వెర్షన్తో యాప్ రీస్టార్ట్ అయిన వెంటనే సేవ స్వయంచాలకంగా తిరిగి వస్తుంది.", + "installWarnBusinessHours": "వ్యాపార వేళల్లో దీన్ని చేయవద్దు.", + "installPinLabel": "మేనేజర్ లేదా యజమాని పిన్", + "installConfirmButton": "ఆమోదించు & రీస్టార్ట్ చేయి", + "installCancelButton": "రద్దు", + "installRestarting": "రీస్టార్ట్ అవుతోంది...", + "installGuardFailedGeneric": "అప్డేట్ ప్రారంభించడం సాధ్యం కాలేదు. మళ్లీ ప్రయత్నించండి.", + "betaTitle": "బీటా అప్డేట్లు (ప్రీ-రిలీజ్లు)", + "betaDescription": "Flo Cafe యొక్క ప్రీ-రిలీజ్ వెర్షన్లు అందరికీ అందుబాటులోకి రాకముందే పొందండి. బీటా బిల్డ్లలో అసంపూర్ణ ఫీచర్లు ఉండవచ్చు.", + "betaUnavailable": "ఈ యాప్ బిల్డ్లో బీటా ఛానెల్ మార్పు ఇంకా అందుబాటులో లేదు. చేరడానికి డెస్క్టాప్ యాప్ను అప్డేట్ చేయండి.", + "betaOn": "ఆన్", + "betaOff": "ఆఫ్", + "betaToggleFailed": "బీటా ఛానెల్ సెట్టింగ్ను మార్చడం సాధ్యం కాలేదు.", + "betaGraduationNote": "బీటా ఛానెల్ నుండి వైదొలగడం వల్ల తదుపరి స్థిరమైన రిలీజ్ ప్రచురించబడే వరకు మీ ప్రస్తుత వెర్షన్ అలాగే ఉంచబడుతుంది, డౌన్గ్రేడ్ల నుండి మీ డేటాబేస్ను రక్షిస్తుంది.", + "availableTitle": "అప్డేట్ అందుబాటులో ఉంది", + "availableDescription": "Flo Cafe యొక్క వెర్షన్ {version} అందుబాటులో ఉంది. ఇప్పుడే డౌన్లోడ్ చేయాలా? అది డౌన్లోడ్ అయ్యేటప్పుడు మీరు పని కొనసాగించవచ్చు, మరియు ఎప్పుడు రీస్టార్ట్ చేయాలో మీరే ఎంచుకోవచ్చు.", + "versionAvailable": "వెర్షన్ {version} అందుబాటులో ఉంది", + "downloadNow": "డౌన్లోడ్", + "later": "తర్వాత", + "downloadFailedToStart": "డౌన్లోడ్ ప్రారంభించడం సాధ్యం కాలేదు. మళ్లీ ప్రయత్నించండి.", + "autoCheckTitle": "అప్డేట్ల కోసం స్వయంచాలకంగా తనిఖీ చేయి", + "autoCheckDescription": "ఆన్లో ఉన్నప్పుడు, Flo Cafe ప్రారంభ సమయంలో కొత్త వెర్షన్ల కోసం తనిఖీ చేస్తుంది మరియు డౌన్లోడ్ చేసే ముందు అడుగుతుంది. ఆఫ్లో ఉన్నప్పుడు, మాన్యువల్గా చూడటానికి అప్డేట్ల కోసం తనిఖీ చేయి ఉపయోగించండి.", + "autoCheckToggleFailed": "ఆటోమేటిక్ అప్డేట్ సెట్టింగ్ను మార్చడం సాధ్యం కాలేదు." + }, + "qrMenu": { + "classicBistro": "క్లాసిక్ బిస్ట్రో", + "connectDrive": "Google Drive కనెక్ట్ చేయి", + "connectHint": "పబ్లిక్, రీడ్-ఓన్లీ మెనూ PDF ప్రచురించడానికి Google Drive కనెక్ట్ చేయండి.", + "copyLink": "లింక్ కాపీ చేయి", + "customPdf": "కస్టమ్ PDF", + "downloadQr": "QR డౌన్లోడ్ చేయి (PNG)", + "generatedMenu": "రూపొందించిన మెనూ", + "includeDescriptions": "వివరణలను చేర్చు", + "includeHidden": "దాచిన వర్గ ఐటెమ్లను చేర్చు", + "includeInactive": "ఇనాక్టివ్ ఐటెమ్లను చేర్చు", + "includeModifiers": "మాడిఫైయర్లను చేర్చు", + "includeOutOfStock": "స్టాక్ లేని ఐటెమ్లను చేర్చు", + "includePhotos": "ఉత్పత్తి ఫోటోలను చేర్చు", + "liveMenu": "లైవ్ QR మెనూ", + "loadFailed": "QR మెనూ సెట్టింగ్లను లోడ్ చేయడం సాధ్యం కాలేదు", + "menuTitle": "మెనూ", + "mobileCafe": "మొబైల్-ఫస్ట్ కేఫ్", + "noProducts": "ఈ మెనూ ఫిల్టర్లకు సరిపోయే ఉత్పత్తులు లేవు", + "notConfigured": "ఈ బిల్డ్లో Google Drive కాన్ఫిగర్ చేయబడలేదు.", + "openMenu": "మెనూ తెరువు", + "pageSize": "పేజీ పరిమాణం", + "pauseSharing": "షేరింగ్ తాత్కాలికంగా నిలిపివేయి", + "pdfInvalid": "చెల్లబాటు అయ్యే PDF ఫైల్ను ఎంచుకోండి", + "pdfOnly": "PDF ఫైళ్లను మాత్రమే అప్లోడ్ చేయవచ్చు", + "pdfTooLarge": "PDF తప్పనిసరిగా 15 MB లేదా అంతకంటే తక్కువ ఉండాలి", + "printCard": "QR టేబుల్ కార్డ్ ప్రింట్ చేయి", + "publishFailed": "QR మెనూను ప్రచురించడం సాధ్యం కాలేదు", + "publishGenerated": "రూపొందించిన మెనూను ప్రచురించు", + "publishMenu": "QR మెనూకు ప్రచురించు", + "published": "QR మెనూ ప్రచురించబడింది", + "qrAlt": "పబ్లిక్ మెనూ కోసం QR కోడ్", + "replaceWithPdf": "కస్టమ్ PDF తో భర్తీ చేయి", + "republish": "QR మెనూ అప్డేట్ చేయి", + "resumeSharing": "షేరింగ్ కొనసాగించు", + "scanPrompt": "మెనూ చూడటానికి స్కాన్ చేయండి", + "sharingFailed": "పబ్లిక్ షేరింగ్ను అప్డేట్ చేయడం సాధ్యం కాలేదు", + "sharingPaused": "పబ్లిక్ షేరింగ్ తాత్కాలికంగా నిలిపివేయబడింది", + "sharingResumed": "పబ్లిక్ షేరింగ్ కొనసాగించబడింది", + "stableLinkHint": "అప్డేట్లు అదే Drive ఫైల్ను భర్తీ చేస్తాయి, కాబట్టి ప్రింట్ చేసిన QR కోడ్లు పనిచేస్తూనే ఉంటాయి.", + "standard": "స్టాండర్డ్", + "template": "మెనూ శైలి", + "title": "QR మెనూ", + "updateMenu": "మెనూ అప్డేట్ చేయి", + "uploadPdf": "కస్టమ్ PDF అప్లోడ్ చేయి" + }, + "whatsapp": { + "active": { + "description": "ఈ పరికరంలో WhatsApp డెలివరీ ఆన్ చేయబడింది.", + "disableConfirm": "WhatsApp నిలిపివేయాలా? కనెక్షన్ మూసివేయబడుతుంది.", + "disableCta": "WhatsApp నిలిపివేయి", + "disableFailed": "నిలిపివేయడం విఫలమైంది.", + "disableTitle": "WhatsApp నిలిపివేయాలా?", + "disabledSuccess": "WhatsApp నిలిపివేయబడింది.", + "title": "యాక్టివ్" + }, + "apiError": { + "bad_connect_method": "విధానం తప్పనిసరిగా “QR” లేదా “పేరింగ్ కోడ్” అయి ఉండాలి", + "body_required": "సందేశ పాఠ్యం అవసరం", + "inbound_not_found": "ఇన్బౌండ్ సందేశం కనుగొనబడలేదు", + "no_pairing_code": "పేరింగ్ కోడ్ అందుబాటులో లేదు. మొదట ఒకదాన్ని అభ్యర్థించండి.", + "no_qr": "QR అందుబాటులో లేదు. మొదట పేరింగ్ సెషన్ను ప్రారంభించండి.", + "phone_not_in_blocklist": "ఫోన్ బ్లాక్లిస్ట్లో లేదు", + "phone_required": "ఫోన్ నంబర్ అవసరం", + "phone_required_pairing": "పేరింగ్ కోడ్ కోసం ఫోన్ అవసరం", + "invalid_phone": "అంతర్జాతీయ ఫార్మాట్లో చెల్లబాటు అయ్యే ఫోన్ నంబర్ నమోదు చేయండి", + "owner_required": "స్టోర్ యజమాని మాత్రమే ఆటోమేటిక్ Z-నివేదిక డెలివరీని కాన్ఫిగర్ చేయగలరు" + }, + "automation": { + "autoOptOutLabel": "ఇన్బౌండ్ STOP / UNSUBSCRIBE పై ఆటో ఆప్ట్-అవుట్ (పంపినవారిని బ్లాక్లిస్ట్కు జోడిస్తుంది)", + "broadcastDescription": "ఫిల్టర్ చేసిన కస్టమర్ విభాగానికి టెంప్లేట్ పంపండి (బ్లాక్లిస్ట్, నిశ్శబ్ద సమయాలు మరియు రేట్ పరిమితులను గౌరవిస్తుంది).", + "broadcastInactiveDays": "ఇనాక్టివ్ >= రోజులు", + "broadcastMinPoints": "కనీస పాయింట్లు", + "broadcastMinVisits": "కనీస సందర్శనలు", + "broadcastSendCta": "బ్రాడ్కాస్ట్ పంపు", + "broadcastSuccess": "బ్రాడ్కాస్ట్ పూర్తయింది: {sent} పంపబడ్డాయి, {skipped} దాటవేయబడ్డాయి ({matched} సరిపోలాయి).", + "broadcastTitle": "కస్టమర్ విభాగం బ్రాడ్కాస్ట్", + "feedbackLinkLabel": "స్టోర్ ఫీడ్బ్యాక్ లింక్", + "instagramLabel": "స్టోర్ Instagram హ్యాండిల్", + "maxPerWeekLabel": "వారానికి ప్రతి కస్టమర్కు గరిష్ట ఆటోమేటెడ్ సందేశాలు", + "placeholdersLabel": "ప్లేస్హోల్డర్ చేర్చడానికి క్లిక్ చేయండి", + "previewTitle": "లైవ్ ప్రివ్యూ (నమూనా డేటా)", + "quietHoursEnd": "నిశ్శబ్ద సమయం ముగింపు", + "quietHoursLabel": "నిశ్శబ్ద సమయాల్లో ఆటోమేటెడ్ పంపడాన్ని ఆపివేయి", + "quietHoursStart": "నిశ్శబ్ద సమయం ప్రారంభం", + "resetDefault": "డిఫాల్ట్కు రీసెట్ చేయి", + "ruleAfterPaymentHint": "కస్టమర్ ఫోన్ ఉన్న బిల్లు చెల్లించినప్పుడు స్వయంచాలకంగా రసీదు టెంప్లేట్ పంపండి.", + "ruleFeedbackDelayHint": "చెల్లించిన ఆర్డర్ తర్వాత ఫాలో-అప్ అభ్యర్థన పంపండి (చెల్లింపు తర్వాత గంటలు).", + "ruleNthVisitHint": "ప్రతి N చెల్లించిన సందర్శనలకు ధన్యవాద రివార్డ్ పంపండి.", + "rulePointsThresholdHint": "పాయింట్ల బ్యాలెన్స్ పరిమితిని దాటినప్పుడు లాయల్టీ రివార్డ్ నోటీసు పంపండి.", + "rulesDescription": "చెల్లింపు తర్వాత రసీదులు, ఫాలో-అప్లు మరియు మైలురాళ్ల కోసం ఆటోమేటెడ్ ట్రిగ్గర్లను టోగుల్ చేయండి మరియు పరిమితులను కాన్ఫిగర్ చేయండి.", + "rulesTitle": "ఆటోమేటెడ్ పంపే నియమాలు", + "ruleWinbackHint": "కనీసం N రోజుల పాటు ఇనాక్టివ్గా ఉన్న కస్టమర్లకు విన్-బ్యాక్ ఆఫర్ పంపండి.", + "runSweepCta": "షెడ్యూల్ చేసిన నియమాలను ఇప్పుడే రన్ చేయి", + "safetyDescription": "ఆటోమేటిక్ ఆప్ట్-అవుట్లు, నిశ్శబ్ద సమయాలు మరియు వారానికి ప్రతి కస్టమర్ పరిమితులతో మీ కనెక్ట్ చేసిన ఫోన్ నంబర్ను రక్షించుకోండి.", + "safetyTitle": "భద్రత & యాంటీ-స్పామ్ నియంత్రణలు", + "saveCta": "ఆటోమేషన్ సెట్టింగ్లను సేవ్ చేయి", + "savedSuccess": "ఆటోమేషన్ సెట్టింగ్లు సేవ్ చేయబడ్డాయి.", + "sweepResult": "షెడ్యూల్ చేసిన నియమాలు తనిఖీ చేయబడ్డాయి ({sent} పంపబడ్డాయి).", + "templateBodyLabel": "సందేశ పాఠ్యం", + "templateNameLabel": "టెంప్లేట్ పేరు", + "templatesDescription": "డైనమిక్ కస్టమర్, బిల్లు, లాయల్టీ మరియు స్టోర్ ప్లేస్హోల్డర్లతో ఆటోమేటెడ్ WhatsApp సందేశాలను అనుకూలీకరించండి.", + "templateSelectLabel": "ఎంచుకున్న టెంప్లేట్", + "templatesTitle": "సందేశ టెంప్లేట్లు", + "thresholdDays": "ఇనాక్టివ్ రోజులు", + "thresholdHours": "ఆలస్య గంటలు", + "thresholdPoints": "పాయింట్ల పరిమితి", + "thresholdVisits": "ప్రతి N సందర్శనలు", + "ruleZReportDayCloseHint": "రోజు ముగించిన తర్వాత యజమాని కాన్ఫిగర్ చేసిన ఫోన్ నంబర్కు స్వయంచాలకంగా Z-నివేదిక పంపండి.", + "zReportOwnerOnlyHint": "స్టోర్ యజమాని మాత్రమే ఈ నియమాన్ని మార్చగలరు.", + "zReportRecipientLabel": "గ్రహీత ఫోన్ (E.164)" + }, + "blocklist": { + "addCta": "జోడించు", + "addedSuccess": "బ్లాక్లిస్ట్కు జోడించబడింది.", + "alreadyBlocked": "ఇప్పటికే బ్లాక్ చేయబడింది.", + "colPhone": "ఫోన్", + "colReason": "కారణం", + "colWhen": "ఎప్పుడు", + "defaultReason": "కస్టమర్ STOP అని చెప్పారు", + "description": "ఇక్కడ ఉన్న నంబర్లకు Flo నుండి ఎప్పుడూ సందేశాలు రావు.", + "empty": "బ్లాక్లిస్ట్ ఖాళీగా ఉంది.", + "failed": "విఫలమైంది.", + "fromInboxSuccess": "{phone} బ్లాక్ చేయబడింది.", + "phoneLabel": "ఫోన్ (E.164)", + "phonePlaceholder": "{dialCode} ఫోన్ నంబర్", + "phoneRequired": "ఫోన్ నంబర్ నమోదు చేయండి.", + "reasonLabel": "కారణం (ఐచ్ఛికం)", + "reasonPlaceholder": "కస్టమర్ STOP అని చెప్పారు", + "removeConfirm": "బ్లాక్లిస్ట్ నుండి {phone} తీసివేయాలా?", + "removeCta": "తీసివేయి", + "title": "బ్లాక్లిస్ట్" + }, + "connect": { + "connectedAs": "కనెక్ట్ అయినది", + "connecting": "కనెక్ట్ అవుతోంది…", + "cooldownFallback": "కూల్డౌన్లో ఉంది.", + "cooldownResumesAt": "{time} కి తిరిగి ప్రారంభమవుతుంది.", + "description": "చెల్లించిన బిల్లులను పంపడానికి Flo కోసం ఫోన్ను లింక్ చేయండి. మీరు కనెక్ట్ చేసే ఫోన్ మీది — దాని బ్యాన్ రిస్క్ మీదే.", + "disconnectConfirm": "WhatsApp నుండి డిస్కనెక్ట్ చేయాలా? మీరు మళ్లీ QR స్కాన్ చేయాలి లేదా మళ్లీ జత చేయాలి.", + "disconnectCta": "డిస్కనెక్ట్ చేయి", + "disconnectFailed": "డిస్కనెక్ట్ చేయడం విఫలమైంది.", + "disconnectTitle": "WhatsApp నుండి డిస్కనెక్ట్ చేయాలా?", + "disconnectedSuccess": "డిస్కనెక్ట్ చేయబడింది.", + "filterGroupsLabel": "WhatsApp గ్రూపుల నుండి వచ్చే సందేశాలను విస్మరించు (గ్రూప్ చాట్లో ఎవరూ డెలివరీ అడగరు). గ్రూప్ సందేశాలను అనుమతించడానికి అన్చెక్ చేయండి.", + "pairingFailed": "జత చేయడం ప్రారంభించడం విఫలమైంది.", + "pairingInstruction": "WhatsApp → సెట్టింగ్లు → లింక్ చేసిన పరికరాలు → పరికరాన్ని లింక్ చేయి తెరిచి → “బదులుగా ఫోన్ నంబర్తో లింక్ చేయి” ట్యాప్ చేసి, నమోదు చేయండి:", + "pairingMethodDescription": "ఫోన్ QR స్కాన్ చేయలేనప్పుడు ఉత్తమమైనది. Flo 8-అంకెల కోడ్ను రూపొందిస్తుంది; మీరు దాన్ని మీ ఫోన్లోని WhatsAppలో టైప్ చేస్తారు.", + "pairingMethodTitle": "పేరింగ్ కోడ్", + "pairingMethodWhere": "మీ ఫోన్లో: WhatsApp → సెట్టింగ్లు → లింక్ చేసిన పరికరాలు → పరికరాన్ని లింక్ చేయి → “బదులుగా ఫోన్ నంబర్తో లింక్ చేయి” ట్యాప్ చేయండి.", + "pairingPhoneLabel": "మీ ఫోన్ నంబర్ (కంట్రీ కోడ్తో)", + "pairingPhonePlaceholder": "{dialCode}XXXXXXXXXX", + "pairingPhoneRequired": "WhatsApp తో జత చేసిన ఫోన్ నంబర్ నమోదు చేయండి.", + "pairingWaiting": "కోడ్ కోసం వేచి ఉంది…", + "qrFailed": "QR ప్రారంభించడం విఫలమైంది.", + "qrGenerating": "QR రూపొందిస్తోంది…", + "qrInstruction": "WhatsApp → సెట్టింగ్లు → లింక్ చేసిన పరికరాలు → పరికరాన్ని లింక్ చేయి తెరిచి, స్కాన్ చేయండి:", + "qrMethodDescription": "ఏ ఫోన్లోనైనా WhatsAppతో స్కాన్ చేయండి — అన్ని ఖాతాలు మరియు ప్లాట్ఫారమ్లకు పనిచేస్తుంది.", + "qrMethodTitle": "QR జత చేయడం", + "qrMethodWhere": "మీ ఫోన్లో: WhatsApp → సెట్టింగ్లు → లింక్ చేసిన పరికరాలు → పరికరాన్ని లింక్ చేయి.", + "qrRefreshHint": "QR స్వయంచాలకంగా రిఫ్రెష్ అవుతుంది.", + "startQr": "QR జత చేయడం ప్రారంభించు", + "title": "ఫోన్ కనెక్ట్ చేయి", + "usePairing": "పేరింగ్ కోడ్ ఉపయోగించు" + }, + "connection": { + "enableInSettings": "సెట్టింగ్లలో ఆన్ చేయి", + "notEnabled": "ఈ టెనెంట్లో WhatsApp ఆన్ చేయబడలేదు." + }, + "enable": { + "ackError": "మొదట బ్యాన్ రిస్క్ను అంగీకరించండి.", + "acknowledge": "నేను బ్యాన్ రిస్క్ను అర్థం చేసుకున్నాను మరియు నా WhatsApp ఆశించే కస్టమర్లకు మాత్రమే సందేశం పంపుతాను.", + "cta": "WhatsApp ఆన్ చేయి", + "description": "ఈ పరికరంతో మీరు జత చేసే ఫోన్ నుండి చెల్లించిన బిల్లులను నేరుగా కస్టమర్ WhatsAppకు పంపండి.", + "failed": "ఆన్ చేయడం విఫలమైంది.", + "floHelps": "STOP అభ్యర్థనలను తక్షణమే గౌరవించడం, గంటకు ప్రతి గ్రహీతకు 4 సందేశాలకు పరిమితం చేయడం మరియు షార్టెనర్ లింక్లను తిరస్కరించడం ద్వారా Flo సహాయపడుతుంది. అయినప్పటికీ: మీ WhatsApp ఆశించే కస్టమర్లకు మాత్రమే సందేశం పంపండి మరియు వారి రికార్డులను తాజాగా ఉంచండి. జత చేసిన నంబర్ బ్యాన్ అయితే, మేము దాన్ని పునరుద్ధరించలేము.", + "riskNote": "ఈ పరికరంతో మీరు జత చేసే ఫోన్ నుండి సందేశాలు వెళ్తాయి. ఆ ఫోన్ నంబర్ నష్టపోయే బాధ్యత మీదే — స్పామ్ లేదా అవాంఛిత సందేశాల కోసం ఉపయోగించే నంబర్లను WhatsApp బ్యాన్ చేస్తుంది, మరియు బ్యాన్ శాశ్వతమైనది.", + "success": "WhatsApp ఆన్ చేయబడింది. ఇప్పుడు పంపడం ప్రారంభించడానికి ఫోన్ను కనెక్ట్ చేయండి.", + "title": "WhatsApp డెలివరీని ఆన్ చేయి" + }, + "inbox": { + "blockCta": "బ్లాక్ చేయి", + "blocked": "బ్లాక్ చేయబడింది", + "copied": "ఫోన్ కాపీ చేయబడింది", + "copyFailed": "క్లిప్బోర్డ్కు కాపీ చేయడం సాధ్యం కాలేదు", + "copyPhone": "ఫోన్ కాపీ చేయి", + "description": "ఇటీవలి 100 ఇన్బౌండ్ సందేశాలు.", + "empty": "ఇంకా ఇన్బౌండ్ సందేశాలు లేవు.", + "emptyHint": "జత చేసిన ఫోన్ సందేశాలను అందుకున్న తర్వాత కస్టమర్ సమాధానాలు ఇక్కడ కనిపిస్తాయి.", + "phoneCopied": "{phone} కాపీ చేయబడింది", + "title": "ఇన్బాక్స్" + }, + "kind": { + "auto_followup": "ఆటో ఫాలో-అప్", + "bill_receipt": "బిల్లు రసీదు", + "manual_reply": "మాన్యువల్ సమాధానం", + "z_report": "Z-నివేదిక", + "daily_sales_report": "రోజువారీ అమ్మకాల నివేదిక" + }, + "lastError": { + "cooldown": "పంపడం తాత్కాలికంగా నిలిపివేయబడింది.", + "logged_out": "లాగ్ అవుట్ అయింది. కొనసాగించడానికి మళ్లీ కనెక్ట్ చేయండి.", + "rate_limited": "WhatsApp ద్వారా పంపడం పరిమితం చేయబడింది ({code}). 5 నిమిషాలు కూల్డౌన్ అవుతోంది.", + "reconnecting": "కనెక్షన్ మూసివేయబడింది ({code}). {seconds}సె లో మళ్లీ కనెక్ట్ అవుతోంది…", + "startup_failed": "WhatsApp కనెక్షన్ ప్రారంభించడం సాధ్యం కాలేదు. మళ్లీ ప్రయత్నించండి." + }, + "rule": { + "after_payment": "చెల్లింపు తర్వాత ఆటో రసీదు", + "broadcast": "విభాగం బ్రాడ్కాస్ట్", + "feedback_delay": "ఫీడ్బ్యాక్ ఫాలో-అప్", + "nth_visit": "Nవ సందర్శన మైలురాయి", + "points_threshold": "లాయల్టీ పాయింట్ల మైలురాయి", + "winback": "ఇనాక్టివ్ కస్టమర్ విన్-బ్యాక్", + "z_report_day_close": "రోజు ముగింపులో Z-నివేదిక" + }, + "send": { + "customerPhoneRequired": "పంపే ముందు ఈ కస్టమర్ ఫోన్ నంబర్ను జోడించండి.", + "error": { + "blocked": "ఈ కస్టమర్ సందేశాలు పంపవద్దని కోరారు. WhatsApp → కనెక్షన్లో బ్లాక్లిస్ట్ను నిర్వహించండి.", + "notConnected": "Flo WhatsAppకు కనెక్ట్ కాలేదు. WhatsApp → కనెక్షన్లో మళ్లీ కనెక్ట్ చేయండి.", + "notOnWhatsapp": "ఈ ఫోన్ WhatsAppలో నమోదు కాలేదు. కస్టమర్తో నంబర్ను మళ్లీ సరిచూసుకోండి.", + "rateLimited": "ఇటీవల ఈ నంబర్కు చాలా సందేశాలు పంపబడ్డాయి." + }, + "failed": "WhatsApp ద్వారా పంపడం విఫలమైంది.", + "success": "WhatsApp ద్వారా రసీదు పంపబడింది." + }, + "sent": { + "colBody": "పాఠ్యం", + "colKind": "రకం", + "colPhone": "ఫోన్", + "colStatus": "స్థితి", + "colWhen": "ఎప్పుడు", + "description": "ఇటీవలి 100 అవుట్బౌండ్ సందేశాలు.", + "empty": "ఇంకా సందేశాలు ఏవీ పంపబడలేదు.", + "emptyHint": "WhatsApp కనెక్ట్ అయి మీరు పంపడం ప్రారంభించిన తర్వాత పంపిన బిల్లులు, మాన్యువల్ సమాధానాలు మరియు ఫాలో-అప్లు ఇక్కడ కనిపిస్తాయి.", + "timeline": "టైమ్లైన్", + "timelineDelivered": "డెలివరీ అయింది: {time}", + "timelineFailed": "విఫలమైంది: {time}", + "timelineQueued": "క్యూలో ఉంది: {time}", + "timelineRead": "చదివారు: {time}", + "timelineSent": "పంపబడింది: {time}", + "timelineTyping": "టైప్ చేస్తున్నారు: {time}", + "title": "పంపిన సందేశాలు" + }, + "settings": { + "enabled": "ఈ టెనెంట్లో WhatsApp ఆన్ చేయబడింది.", + "enabledHint": "WhatsApp పేజీ నుండి కనెక్షన్ను నిర్వహించండి.", + "openConnection": "కనెక్షన్ తెరువు" + }, + "state": { + "connected": "కనెక్ట్ చేయబడింది", + "connecting": "కనెక్ట్ అవుతోంది", + "cooldown": "కూల్డౌన్లో ఉంది", + "disconnected": "డిస్కనెక్ట్ చేయబడింది", + "reconnecting": "మళ్లీ కనెక్ట్ అవుతోంది…", + "repair_needed": "మళ్లీ జత చేయడం అవసరం", + "waiting_pairing": "పేరింగ్ కోడ్ కోసం వేచి ఉంది", + "waiting_qr": "QR స్కాన్ కోసం వేచి ఉంది" + }, + "status": { + "delivered": "డెలివరీ చేయబడింది", + "failed": "విఫలమైంది", + "notSent": "పంపిన రికార్డు లేదు", + "partial": "పాక్షికంగా పంపబడింది", + "pending": "పెండింగ్", + "queued": "క్యూలో ఉంది", + "read": "చదివారు", + "sent": "పంపబడింది", + "typing": "టైప్ చేస్తున్నారు" + }, + "step": { + "delivered": "డెలివరీ చేయబడింది", + "queued": "క్యూలో ఉంది", + "read": "చదివారు", + "sent": "పంపబడింది", + "typing": "టైప్ చేస్తున్నారు" + }, + "tabs": { + "automation": "టెంప్లేట్లు & నియమాలు", + "connection": "కనెక్షన్", + "inbox": "ఇన్బాక్స్", + "sent": "పంపినవి" + } + } +} diff --git a/frontend/src/lib/printer/PrinterService.ts b/frontend/src/lib/printer/PrinterService.ts index 1c1d42582..2bea30ed5 100644 --- a/frontend/src/lib/printer/PrinterService.ts +++ b/frontend/src/lib/printer/PrinterService.ts @@ -329,7 +329,7 @@ class PrinterService { @page { size: ${mmWidth} auto; margin: 0; } * { margin: 0; padding: 0; box-sizing: border-box; } body { - font-family: 'Courier New', 'Noto Sans Devanagari', 'Nirmala UI', 'Kohinoor Devanagari', 'Devanagari Sangam MN', 'Noto Sans Gurmukhi', 'Raavi', 'Kohinoor Gurmukhi', 'Gurmukhi Sangam MN', 'Noto Sans Thai', 'Leelawadee UI', Thonburi, monospace; + font-family: 'Courier New', 'Noto Sans Devanagari', 'Nirmala UI', 'Kohinoor Devanagari', 'Devanagari Sangam MN', 'Noto Sans Gurmukhi', 'Raavi', 'Kohinoor Gurmukhi', 'Gurmukhi Sangam MN', 'Noto Sans Telugu', 'Kohinoor Telugu', 'Telugu Sangam MN', 'Noto Sans Thai', 'Leelawadee UI', Thonburi, monospace; font-size: 13px; font-weight: 600; color: #000; diff --git a/frontend/src/lib/printer/delivery-slip-web-print.ts b/frontend/src/lib/printer/delivery-slip-web-print.ts index 5a363d612..582659f6b 100644 --- a/frontend/src/lib/printer/delivery-slip-web-print.ts +++ b/frontend/src/lib/printer/delivery-slip-web-print.ts @@ -137,7 +137,7 @@ export function generateDeliverySlipHtml( : `
${escapeHtml(tr(payment.status === 'refunded' ? 'print.deliverySlip.refunded' : 'print.deliverySlip.partiallyRefunded'))}
${escapeHtml(tr('print.deliverySlip.amountDue'))}: ${escapeHtml(payment.formattedAmountDue ?? '')}
`; return ` -
+

${escapeHtml(tr('print.deliverySlip.banner'))}

#${escapeHtml(order.order_number)}

${escapeHtml(tr('print.time'))}: ${escapeHtml(formatTime(order.created_at, locale, timezone ? { timeZone: timezone } : undefined))}

diff --git a/frontend/src/lib/printer/kot-web-print.ts b/frontend/src/lib/printer/kot-web-print.ts index a22907463..d7ba330b1 100644 --- a/frontend/src/lib/printer/kot-web-print.ts +++ b/frontend/src/lib/printer/kot-web-print.ts @@ -130,6 +130,7 @@ const KOT_FONT_STACKS_BY_SCRIPT: Record = { Jpan: `'Yu Gothic', Meiryo, 'Hiragino Sans', 'Noto Sans CJK JP', 'Noto Sans JP', ${KOT_MONOSPACE_TAIL}`, Kore: `'Noto Sans', ${KOT_MONOSPACE_TAIL}`, Latn: `'Courier New',monospace`, + Telu: `'Noto Sans Telugu', 'Nirmala UI', 'Kohinoor Telugu', 'Telugu Sangam MN', ${KOT_MONOSPACE_TAIL}`, Thai: `'Noto Sans Thai', 'Leelawadee UI', Thonburi, ${KOT_MONOSPACE_TAIL}`, }; diff --git a/frontend/src/lib/printer/order-slip-web-print.ts b/frontend/src/lib/printer/order-slip-web-print.ts index e8bdfc2a0..1f5f19703 100644 --- a/frontend/src/lib/printer/order-slip-web-print.ts +++ b/frontend/src/lib/printer/order-slip-web-print.ts @@ -96,7 +96,7 @@ export function generateOrderSlipHtml( .join(''); return ` -
+

${escapeHtml(labels.title)}

#${escapeHtml(order.order_number)}

${order.table?.name ? `

${escapeHtml(order.table.name)}

` : ''} diff --git a/frontend/src/lib/printer/web-print.ts b/frontend/src/lib/printer/web-print.ts index bf82d3c7e..2b4898be7 100644 --- a/frontend/src/lib/printer/web-print.ts +++ b/frontend/src/lib/printer/web-print.ts @@ -548,7 +548,7 @@ export function getPaperStyles(size: PaperSize, textSize?: PrinterTextSize): str const normalizedTextSize = normalizePrinterTextSize(textSize); const baseStyles = ` * { box-sizing: border-box; margin: 0; padding: 0; } - body { font-family: -apple-system, 'Segoe UI', Tahoma, 'Noto Naskh Arabic', 'Noto Sans Bengali', 'Vrinda', 'Bangla Sangam MN', 'Noto Sans Devanagari', 'Nirmala UI', 'Kohinoor Devanagari', 'Devanagari Sangam MN', 'Noto Sans Gurmukhi', 'Raavi', 'Kohinoor Gurmukhi', 'Gurmukhi Sangam MN', 'Noto Sans Thai', 'Leelawadee UI', Thonburi, 'PingFang SC', 'Microsoft YaHei', 'Noto Sans CJK SC', 'Hiragino Sans', 'Yu Gothic', 'Meiryo', 'Noto Sans CJK JP', 'Noto Sans JP', 'Helvetica Neue', Arial, sans-serif; font-size: 13px; font-weight: 600; line-height: 1.4; color: #000; } + body { font-family: -apple-system, 'Segoe UI', Tahoma, 'Noto Naskh Arabic', 'Noto Sans Bengali', 'Vrinda', 'Bangla Sangam MN', 'Noto Sans Devanagari', 'Nirmala UI', 'Kohinoor Devanagari', 'Devanagari Sangam MN', 'Noto Sans Gurmukhi', 'Raavi', 'Kohinoor Gurmukhi', 'Gurmukhi Sangam MN', 'Noto Sans Telugu', 'Kohinoor Telugu', 'Telugu Sangam MN', 'Noto Sans Thai', 'Leelawadee UI', Thonburi, 'PingFang SC', 'Microsoft YaHei', 'Noto Sans CJK SC', 'Hiragino Sans', 'Yu Gothic', 'Meiryo', 'Noto Sans CJK JP', 'Noto Sans JP', 'Helvetica Neue', Arial, sans-serif; font-size: 13px; font-weight: 600; line-height: 1.4; color: #000; } body:lang(zh-TW) { font-family: -apple-system, 'Segoe UI', Tahoma, 'Noto Naskh Arabic', 'PingFang TC', 'Microsoft JhengHei', 'Noto Sans CJK TC', 'Noto Sans TC', 'Helvetica Neue', Arial, sans-serif; } .bill-container { max-width: 100%; margin: 0 auto; color: #000; } .reprint-banner { text-align: center; font-size: 20px; font-weight: 700; letter-spacing: 2px; color: #000; border: 2px solid #000; padding: 6px; margin-bottom: 12px; } diff --git a/main/print/print-labels.generated.ts b/main/print/print-labels.generated.ts index 67544cd94..126604132 100644 --- a/main/print/print-labels.generated.ts +++ b/main/print/print-labels.generated.ts @@ -35,6 +35,7 @@ export const PRINT_LABEL_LANGUAGES = [ 'mr', 'sw', 'pa', + 'te', ] as const; export type PrintLabelLanguage = (typeof PRINT_LABEL_LANGUAGES)[number]; @@ -4305,6 +4306,153 @@ const PRINT_LABELS: Record = { 'common.unknown': "ਅਣਜਾਣ", 'orders.pending': "ਬਕਾਇਆ", }, + "te": { + 'print.menu.title': "మెనూ", + 'print.menu.totalItems': "మొత్తం ఐటెమ్లు", + 'print.taxInvoiceTitle': "పన్ను ఇన్వాయిస్", + 'print.invoiceTitle': "ఇన్వాయిస్", + 'print.invoiceNumber': "ఇన్వాయిస్ #:", + 'print.time': "సమయం", + 'print.customerShort': "కస్టమర్", + 'print.numberShort': "కస్టమర్ నం", + 'print.customerDetails': "కస్టమర్ వివరాలు", + 'print.address': "చిరునామా", + 'print.call': "కాల్", + 'print.note': "గమనిక", + 'print.phoneLong': "ఫోన్", + 'print.subtotalExclTax': "ఉప మొత్తం (పన్ను మినహా)", + 'print.serviceChargeShort': "సర్వీస్ ఛార్జ్", + 'print.grandTotal': "మొత్తం", + 'print.thankYouShort': "ధన్యవాదాలు!", + 'print.thankYouVisitAgain': "మీ సందర్శనకు ధన్యవాదాలు!", + 'print.pleaseComeAgain': "దయచేసి మళ్లీ రండి!", + 'print.ratesInclusiveNote': "ధరలలో పన్నులు కలిసి ఉంటాయి", + 'print.pointsEarned': "సంపాదించిన పాయింట్లు", + 'print.pointsBalance': "పాయింట్ల బ్యాలెన్స్", + 'print.pointsRedeemed': "రిడీమ్ చేసిన పాయింట్లు", + 'print.kot.title': "కిచెన్ ఆర్డర్ టికెట్", + 'print.kot.banner': "కిచెన్ ఆర్డర్ టికెట్", + 'print.kot.station': "స్టేషన్", + 'print.kot.type': "రకం", + 'print.kot.noPendingItems': "పెండింగ్ ఐటెమ్లు లేవు", + 'print.kot.end': "ముగింపు", + 'print.deliverySlip.title': "డెలివరీ స్లిప్", + 'print.deliverySlip.banner': "డెలివరీ స్లిప్", + 'print.deliverySlip.address': "డెలివరీ చిరునామా", + 'print.deliverySlip.addressTruncated': "... మరో {count} అక్షరాలు చూపబడలేదు, ఆర్డర్ను తనిఖీ చేయండి", + 'print.deliverySlip.paid': "చెల్లించబడింది", + 'print.deliverySlip.toCollect': "వసూలు చేయాల్సింది", + 'print.deliverySlip.refunded': "రీఫండ్ చేయబడింది", + 'print.deliverySlip.partiallyRefunded': "పాక్షికంగా రీఫండ్ చేయబడింది", + 'print.deliverySlip.cashOnDelivery': "క్యాష్ ఆన్ డెలివరీ", + 'print.deliverySlip.amountDue': "చెల్లించాల్సిన మొత్తం", + 'print.deliverySlip.multiplePaymentMethods': "బహుళ చెల్లింపు విధానాలు", + 'print.deliverySlip.expectedPayment': "ఆశించిన చెల్లింపు", + 'print.deliverySlip.deliveryNote': "డెలివరీ గమనిక", + 'print.hsn': "HSN", + 'print.zReport.title': "Z నివేదిక", + 'print.zReport.businessDate': "తేదీ:", + 'print.zReport.periodStart': "వ్యవధి ప్రారంభం:", + 'print.zReport.periodEnd': "వ్యవధి ముగింపు:", + 'print.zReport.openingFloat': "ప్రారంభ నగదు", + 'print.zReport.cashMovements': "నగదు లావాదేవీలు", + 'print.zReport.payIn': "నగదు జమ", + 'print.zReport.payOut': "నగదు ఉపసంహరణ", + 'print.zReport.safeDrop': "సేఫ్ డ్రాప్", + 'print.zReport.payments': "చెల్లింపు విధానం వారీగా అమ్మకాలు", + 'print.zReport.refunds': "రీఫండ్లు", + 'print.zReport.tax': "పన్ను వివరాలు", + 'print.zReport.staff': "సిబ్బంది అమ్మకాలు", + 'print.zReport.expectedCash': "ఆశించిన నగదు", + 'print.zReport.countedCash': "లెక్కించిన నగదు", + 'print.zReport.variance': "తేడా", + 'print.zReport.closedBy': "మూసివేసినవారు:", + 'print.zReport.operatorSignature': "ఆపరేటర్ సంతకం:", + 'print.zReport.footer': "FloCafe ద్వారా రూపొందించబడింది", + 'print.zReport.none': "(ఏదీ లేదు)", + 'print.zReport.paymentCount': "x{count}", + 'print.zReport.count': "సంఖ్య:", + 'print.zReport.amount': "మొత్తం:", + 'print.test.title': "Flo ప్రింటర్ టెస్ట్", + 'print.test.networkUsb': "నెట్వర్క్ / USB టెస్ట్ ప్రింట్", + 'print.test.columns': "నిలువు వరుసలు", + 'print.test.wrapHint': "తదుపరి లైన్ చుట్టుకుంటే, తక్కువ నిలువు వరుసల విలువను ఎంచుకోండి.", + 'print.test.success': "మీరు దీన్ని చదవగలిగితే, మీ ప్రింటర్ పనిచేస్తోంది!", + 'receipt.billNumber': "బిల్లు #", + 'receipt.date': "తేదీ", + 'pos.tableLabel': "టేబుల్: {name}", + 'pos.customer': "కస్టమర్", + 'receipt.customerNo': "కస్టమర్ నం", + 'receipt.phone': "ఫోన్", + 'receipt.item': "ఐటెమ్", + 'receipt.qty': "పరిమాణం", + 'receipt.rate': "ధర", + 'receipt.amount': "మొత్తం", + 'printTest.amt': "మొత్తం", + 'pos.subtotal': "ఉప మొత్తం", + 'pos.discount': "తగ్గింపు", + 'pos.tax': "పన్ను", + 'pos.total': "మొత్తం", + 'pos.delivery': "డెలివరీ", + 'pos.packaging': "ప్యాకేజింగ్", + 'receipt.totalTax': "మొత్తం పన్ను", + 'receipt.serviceCharge': "సర్వీస్ ఛార్జ్", + 'receipt.taxDetails': "పన్ను వివరాలు", + 'receipt.payments': "చెల్లింపులు", + 'receipt.cashReceived': "స్వీకరించిన నగదు", + 'receipt.thankYou': "మీ సందర్శనకు ధన్యవాదాలు!", + 'receipt.taxIncluded': "వర్తించే చోట పన్ను కలిపి ఉంటుంది", + 'receipt.reprint': "రీప్రింట్", + 'receipt.onlineOrder': "ఆన్లైన్ ఆర్డర్", + 'pos.orderNumber': "ఆర్డర్ #{number}", + 'pos.orderTypeDineIn': "డైన్-ఇన్", + 'pos.orderTypeDelivery': "డెలివరీ", + 'pos.orderTypeOnline': "ఆన్లైన్", + 'pos.orderTypeTakeaway': "టేక్అవే", + 'pos.methodCash': "నగదు", + 'pos.methodCard': "కార్డ్", + 'pos.methodWallet': "వాలెట్", + 'pos.changeReturned': "తిరిగి ఇచ్చిన చిల్లర", + 'dashboard.zReport': "Z నివేదిక", + 'dashboard.businessDateLabel': "వ్యాపార తేదీ", + 'dashboard.periodStart': "వ్యవధి ప్రారంభం", + 'dashboard.periodEnd': "వ్యవధి ముగింపు", + 'dashboard.ticketCount': "సంఖ్య", + 'dashboard.ticketOperatorSignature': "ఆపరేటర్ సంతకం", + 'dashboard.openingFloat': "ప్రారంభ నగదు", + 'dashboard.ticketSectionPayments': "చెల్లింపు విధానాలు", + 'dashboard.ticketSectionRefunds': "రీఫండ్లు", + 'dashboard.ticketSectionTax': "పన్ను వివరాలు", + 'dashboard.ticketSectionStaff': "సిబ్బంది అమ్మకాలు", + 'dashboard.ticketSectionOperator': "మూసివేసినవారు", + 'dashboard.ticketNoPayments': "ఈ రోజుకు చెల్లింపులు లేవు", + 'dashboard.ticketNoRefunds': "రీఫండ్లు లేవు", + 'dashboard.ticketNoTax': "పన్ను లేదు", + 'dashboard.ticketNoStaff': "సిబ్బంది అమ్మకాలు లేవు", + 'dashboard.ticketMethodCount': "{count} ×", + 'dashboard.expectedCash': "ఆశించిన నగదు", + 'dashboard.countedCash': "లెక్కించిన నగదు", + 'dashboard.variance': "తేడా", + 'dashboard.ticketFooter': "FloCafe ద్వారా రూపొందించబడింది", + 'dashboard.dailySalesWhatsAppTitle': "రోజువారీ అమ్మకాల నివేదిక", + 'dashboard.salesSummary': "అమ్మకాల సారాంశం", + 'dashboard.grossCollections': "స్థూల వసూళ్లు", + 'dashboard.refunds': "రీఫండ్లు", + 'dashboard.netCollections': "నికర వసూళ్లు", + 'dashboard.paymentMethods': "చెల్లింపు విధానాలు", + 'dashboard.paymentBreakdown': "చెల్లింపులు", + 'dashboard.topProducts': "అగ్ర ఉత్పత్తులు", + 'dashboard.billsCount': "బిల్లులు: {count}", + 'dashboard.ordersCount': "ఆర్డర్లు: {count}", + 'dashboard.periodWindow': "వ్యవధి: {start} నుండి {end} వరకు", + 'dashboard.drawerReconciliation': "డ్రాయర్ సరిపోలిక", + 'dashboard.varianceExact': "ఖచ్చితంగా సరిపోయింది", + 'dashboard.varianceShort': "తక్కువ", + 'dashboard.varianceOver': "ఎక్కువ", + 'dashboard.closureNotes': "గమనికలు", + 'common.unknown': "తెలియదు", + 'orders.pending': "పెండింగ్", + }, }; /** diff --git a/main/services/cash-close-export.ts b/main/services/cash-close-export.ts index a1937c4f5..1708482aa 100644 --- a/main/services/cash-close-export.ts +++ b/main/services/cash-close-export.ts @@ -360,7 +360,7 @@ function serializeHtml( body { margin: 0; padding: 0; - font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Noto Naskh Arabic", "Noto Sans Arabic", "Noto Sans Bengali", "Vrinda", "Bangla Sangam MN", "Noto Sans Devanagari", "Nirmala UI", "Kohinoor Devanagari", "Devanagari Sangam MN", "Noto Sans Gurmukhi", "Raavi", "Kohinoor Gurmukhi", "Gurmukhi Sangam MN", "Noto Sans Thai", "Leelawadee UI", "Thonburi", "PingFang SC", "Microsoft YaHei", "Noto Sans CJK SC", "PingFang TC", "Microsoft JhengHei", "Noto Sans CJK TC", "Noto Sans TC", "Hiragino Sans", "Yu Gothic", "Meiryo", "Noto Sans CJK JP", "Noto Sans JP", "Noto Sans", "Helvetica Neue", Arial, sans-serif; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Noto Naskh Arabic", "Noto Sans Arabic", "Noto Sans Bengali", "Vrinda", "Bangla Sangam MN", "Noto Sans Devanagari", "Nirmala UI", "Kohinoor Devanagari", "Devanagari Sangam MN", "Noto Sans Gurmukhi", "Raavi", "Kohinoor Gurmukhi", "Gurmukhi Sangam MN", "Noto Sans Telugu", "Kohinoor Telugu", "Telugu Sangam MN", "Noto Sans Thai", "Leelawadee UI", "Thonburi", "PingFang SC", "Microsoft YaHei", "Noto Sans CJK SC", "PingFang TC", "Microsoft JhengHei", "Noto Sans CJK TC", "Noto Sans TC", "Hiragino Sans", "Yu Gothic", "Meiryo", "Noto Sans CJK JP", "Noto Sans JP", "Noto Sans", "Helvetica Neue", Arial, sans-serif; font-size: 11px; line-height: 1.45; color: #111827; diff --git a/main/services/daily-invoices-export.ts b/main/services/daily-invoices-export.ts index f42389602..9032890f5 100644 --- a/main/services/daily-invoices-export.ts +++ b/main/services/daily-invoices-export.ts @@ -201,6 +201,7 @@ const REPORT_FONT_STACK = [ '"Noto Sans Devanagari"', '"Noto Sans Gurmukhi"', '"Noto Sans Bengali"', + '"Noto Sans Telugu"', '"Noto Sans Tamil"', '"Noto Sans Thai"', '"Noto Sans CJK SC"', diff --git a/main/services/daily-sales-export.ts b/main/services/daily-sales-export.ts index 675bd7148..370323c5f 100644 --- a/main/services/daily-sales-export.ts +++ b/main/services/daily-sales-export.ts @@ -2038,7 +2038,7 @@ export function serializeDailySalesExportHtml( body { margin: 0; padding: 0; - font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Noto Naskh Arabic", "Noto Sans Arabic", "Noto Sans Bengali", "Vrinda", "Bangla Sangam MN", "Noto Sans Devanagari", "Nirmala UI", "Kohinoor Devanagari", "Devanagari Sangam MN", "Noto Sans Gurmukhi", "Raavi", "Kohinoor Gurmukhi", "Gurmukhi Sangam MN", "Noto Sans Thai", "Leelawadee UI", "Thonburi", "PingFang SC", "Microsoft YaHei", "Noto Sans CJK SC", "PingFang TC", "Microsoft JhengHei", "Noto Sans CJK TC", "Noto Sans TC", "Hiragino Sans", "Yu Gothic", "Meiryo", "Noto Sans CJK JP", "Noto Sans JP", "Noto Sans", "Helvetica Neue", Arial, sans-serif; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Noto Naskh Arabic", "Noto Sans Arabic", "Noto Sans Bengali", "Vrinda", "Bangla Sangam MN", "Noto Sans Devanagari", "Nirmala UI", "Kohinoor Devanagari", "Devanagari Sangam MN", "Noto Sans Gurmukhi", "Raavi", "Kohinoor Gurmukhi", "Gurmukhi Sangam MN", "Noto Sans Telugu", "Kohinoor Telugu", "Telugu Sangam MN", "Noto Sans Thai", "Leelawadee UI", "Thonburi", "PingFang SC", "Microsoft YaHei", "Noto Sans CJK SC", "PingFang TC", "Microsoft JhengHei", "Noto Sans CJK TC", "Noto Sans TC", "Hiragino Sans", "Yu Gothic", "Meiryo", "Noto Sans CJK JP", "Noto Sans JP", "Noto Sans", "Helvetica Neue", Arial, sans-serif; font-size: 10px; line-height: 1.4; color: #111827; diff --git a/main/setup/seed-data.ts b/main/setup/seed-data.ts index 7ef86a58e..94323b537 100644 --- a/main/setup/seed-data.ts +++ b/main/setup/seed-data.ts @@ -115,7 +115,8 @@ type SeedLanguage = | 'jv' | 'mr' | 'sw' - | 'pa'; + | 'pa' + | 'te'; /** Filipino intentionally uses the English sample data as its reviewed exception. */ export const ENGLISH_IDENTICAL_SEED_LANGUAGES = ['fil'] as const; @@ -148,7 +149,8 @@ function resolveSeedLanguage(language?: string): SeedLanguage { language === 'jv' || language === 'mr' || language === 'sw' || - language === 'pa' + language === 'pa' || + language === 'te' ? language : 'en'; } @@ -189,6 +191,7 @@ function seedExpressRestaurant( mr: ['खाद्यपदार्थ', 'पेये', 'जेवण', 'चहा'], sw: ['Chakula', 'Vinywaji', 'Mlo', 'Chai'], pa: ['ਖਾਣਾ', 'ਪੀਣ ਵਾਲੇ ਪਦਾਰਥ', 'ਭੋਜਨ', 'ਚਾਹ'], + te: ['ఆహారం', 'పానీయాలు', 'భోజనం', 'టీ'], }; const [food, beverages, meal, tea] = labels[lang]; const coffee = @@ -244,7 +247,9 @@ function seedExpressRestaurant( ? 'Kahawa' : lang === 'pa' ? 'ਕੌਫੀ' - : 'Coffee'; + : lang === 'te' + ? 'కాఫీ' + : 'Coffee'; const snack = lang === 'es' ? 'Bocadillo' @@ -300,7 +305,9 @@ function seedExpressRestaurant( ? 'Vitafunio' : lang === 'pa' ? 'ਨਾਸ਼ਤਾ' - : 'Snack'; + : lang === 'te' + ? 'చిరుతిండి' + : 'Snack'; insertCategory(db, 'cat-express-food', food, '#F97316', '🍽️', 1); insertCategory(db, 'cat-express-beverages', beverages, '#0EA5E9', '🥤', 2); insertProduct(db, 'prod-express-meal', 'cat-express-food', meal, 150, 1); @@ -705,36 +712,67 @@ function seedDemoRestaurant( 4, ], ] as const) - : ([ - [ - 'cat-demo-starters', - 'Starters', - '#FF6B6B', - '🍔', - 1, - ], - [ - 'cat-demo-main', - 'Main Course', - '#4ECDC4', - '🍛', - 2, - ], - [ - 'cat-demo-beverages', - 'Beverages', - '#45B7D1', - '🥤', - 3, - ], - [ - 'cat-demo-desserts', - 'Desserts', - '#96CEB4', - '🍰', - 4, - ], - ] as const); + : lang === 'te' + ? ([ + [ + 'cat-demo-starters', + 'స్టార్టర్లు', + '#FF6B6B', + '🍟', + 1, + ], + [ + 'cat-demo-main', + 'ప్రధాన వంటకాలు', + '#4ECDC4', + '🍛', + 2, + ], + [ + 'cat-demo-beverages', + 'పానీయాలు', + '#45B7D1', + '🥤', + 3, + ], + [ + 'cat-demo-desserts', + 'మిఠాయిలు', + '#96CEB4', + '🍰', + 4, + ], + ] as const) + : ([ + [ + 'cat-demo-starters', + 'Starters', + '#FF6B6B', + '🍔', + 1, + ], + [ + 'cat-demo-main', + 'Main Course', + '#4ECDC4', + '🍛', + 2, + ], + [ + 'cat-demo-beverages', + 'Beverages', + '#45B7D1', + '🥤', + 3, + ], + [ + 'cat-demo-desserts', + 'Desserts', + '#96CEB4', + '🍰', + 4, + ], + ] as const); for (const [id, name, color, icon, sort] of cats) insertCategory(db, id, name, color, icon, sort); const products = @@ -1701,64 +1739,123 @@ function seedDemoRestaurant( 1, ], ] as const) - : ([ - [ - 'prod-demo-paneer-tikka', - 'cat-demo-starters', - 'Paneer Tikka', - 250, - 1, - ], - [ - 'prod-demo-chicken-wings', - 'cat-demo-starters', - 'Chicken Wings', - 280, - 2, - ], - [ - 'prod-demo-butter-chicken', - 'cat-demo-main', - 'Butter Chicken', - 320, - 1, - ], - [ - 'prod-demo-dal-makhani', - 'cat-demo-main', - 'Dal Makhani', - 220, - 2, - ], - [ - 'prod-demo-jeera-rice', - 'cat-demo-main', - 'Jeera Rice', - 150, - 3, - ], - [ - 'prod-demo-cola', - 'cat-demo-beverages', - 'Cola', - 60, - 1, - ], - [ - 'prod-demo-lemon-soda', - 'cat-demo-beverages', - 'Lemon Soda', - 70, - 2, - ], - [ - 'prod-demo-gulab-jamun', - 'cat-demo-desserts', - 'Gulab Jamun', - 80, - 1, - ], - ] as const); + : lang === 'te' + ? ([ + [ + 'prod-demo-punugulu', + 'cat-demo-starters', + 'పునుగులు', + 250, + 1, + ], + [ + 'prod-demo-garelu', + 'cat-demo-starters', + 'గారెలు', + 280, + 2, + ], + [ + 'prod-demo-hyderabadi-biryani', + 'cat-demo-main', + 'హైదరాబాదీ బిర్యానీ', + 320, + 1, + ], + [ + 'prod-demo-gutti-vankaya', + 'cat-demo-main', + 'గుత్తి వంకాయ కూర', + 220, + 2, + ], + [ + 'prod-demo-pappu-annam', + 'cat-demo-main', + 'పప్పు అన్నం', + 150, + 3, + ], + [ + 'prod-demo-filter-coffee', + 'cat-demo-beverages', + 'ఫిల్టర్ కాఫీ', + 60, + 1, + ], + [ + 'prod-demo-majjiga', + 'cat-demo-beverages', + 'మజ్జిగ', + 70, + 2, + ], + [ + 'prod-demo-pootharekulu', + 'cat-demo-desserts', + 'పూతరేకులు', + 80, + 1, + ], + ] as const) + : ([ + [ + 'prod-demo-paneer-tikka', + 'cat-demo-starters', + 'Paneer Tikka', + 250, + 1, + ], + [ + 'prod-demo-chicken-wings', + 'cat-demo-starters', + 'Chicken Wings', + 280, + 2, + ], + [ + 'prod-demo-butter-chicken', + 'cat-demo-main', + 'Butter Chicken', + 320, + 1, + ], + [ + 'prod-demo-dal-makhani', + 'cat-demo-main', + 'Dal Makhani', + 220, + 2, + ], + [ + 'prod-demo-jeera-rice', + 'cat-demo-main', + 'Jeera Rice', + 150, + 3, + ], + [ + 'prod-demo-cola', + 'cat-demo-beverages', + 'Cola', + 60, + 1, + ], + [ + 'prod-demo-lemon-soda', + 'cat-demo-beverages', + 'Lemon Soda', + 70, + 2, + ], + [ + 'prod-demo-gulab-jamun', + 'cat-demo-desserts', + 'Gulab Jamun', + 80, + 1, + ], + ] as const); for (const [id, categoryId, name, price, sort] of products) insertProduct(db, id, categoryId, name, price, sort); @@ -1885,6 +1982,10 @@ function seedDemoRestaurant( insertCustomer(db, 'cust-demo-1', 'ਹਰਪ੍ਰੀਤ ਸਿੰਘ', '+919876543210', dialCode, demoCountry); insertCustomer(db, 'cust-demo-2', 'ਸਿਮਰਨ ਕੌਰ', '+919876543211', dialCode, demoCountry); insertCustomer(db, 'cust-demo-3', 'ਗੁਰਪ੍ਰੀਤ ਗਿੱਲ', '+919876543212', dialCode, demoCountry); + } else if (lang === 'te') { + insertCustomer(db, 'cust-demo-1', 'రవి కుమార్', '+919876543210', dialCode, demoCountry); + insertCustomer(db, 'cust-demo-2', 'లక్ష్మీ దేవి', '+919876543211', dialCode, demoCountry); + insertCustomer(db, 'cust-demo-3', 'వెంకట రావు', '+919876543212', dialCode, demoCountry); } else { insertCustomer(db, 'cust-demo-1', 'Aarav Sharma', '+919876543210', dialCode, demoCountry); insertCustomer(db, 'cust-demo-2', 'Maya Iyer', '+919876543211', dialCode, demoCountry); @@ -1946,7 +2047,9 @@ function seedDemoRestaurant( ? 'Meneja wa Mfano' : lang === 'pa' ? 'ਡੈਮੋ ਮੈਨੇਜਰ' - : 'Demo Manager'; + : lang === 'te' + ? 'డెమో మేనేజర్' + : 'Demo Manager'; const cashierName = lang === 'es' ? 'Cajero Demo' @@ -2002,7 +2105,9 @@ function seedDemoRestaurant( ? 'Keshia wa Mfano' : lang === 'pa' ? 'ਡੈਮੋ ਕੈਸ਼ੀਅਰ' - : 'Demo Cashier'; + : lang === 'te' + ? 'డెమో క్యాషియర్' + : 'Demo Cashier'; const chefName = lang === 'es' ? 'Cocinero Demo' @@ -2058,7 +2163,9 @@ function seedDemoRestaurant( ? 'Mpishi wa Mfano' : lang === 'pa' ? 'ਡੈਮੋ ਸ਼ੈੱਫ' - : 'Demo Chef'; + : lang === 'te' + ? 'డెమో చెఫ్' + : 'Demo Chef'; // Demo staff accounts are inactive with random passwords to prevent usable default credentials. insertStaffUser( db, diff --git a/main/status-messages.ts b/main/status-messages.ts index 12c2d7566..8e4760dca 100644 --- a/main/status-messages.ts +++ b/main/status-messages.ts @@ -328,6 +328,16 @@ const TABLES: Record = { shutdownBackup: ['ਬੈਕਅੱਪ ਲਿਆ ਜਾ ਰਿਹਾ ਹੈ', 'ਕਿਰਪਾ ਕਰਕੇ ਕੰਪਿਊਟਰ ਬੰਦ ਨਾ ਕਰੋ।'], saved: ['ਸਭ ਕੁਝ ਸੰਭਾਲ ਲਿਆ ਗਿਆ', 'Flo ਕੁਝ ਹੀ ਪਲਾਂ ਵਿੱਚ ਬੰਦ ਹੋ ਜਾਵੇਗਾ।'], }, + te: { + starting: ['Flo ప్రారంభమవుతోంది', 'అన్నీ సిద్ధం చేస్తున్నాము…'], + checking: ['మీ డేటా తనిఖీ చేయబడుతోంది', 'డేటాబేస్ ధృవీకరించి ఆరోగ్యంగా ఉంచుతున్నాము…'], + backingUp: ['మీ డేటా బ్యాకప్ చేయబడుతోంది', 'ప్రారంభించే ముందు సురక్షిత కాపీని సేవ్ చేస్తున్నాము…'], + services: ['సేవలు ప్రారంభమవుతున్నాయి', 'దాదాపు పూర్తయింది…'], + welcome: ['Flo కు స్వాగతం', 'మీ వర్క్ స్పేస్ తెరవబడుతోంది…'], + closing: ['Flo మూసివేయబడుతోంది', 'మీ డేటా సేవ్ చేయబడుతోంది. దయచేసి కంప్యూటర్ ఆఫ్ చేయవద్దు.'], + shutdownBackup: ['బ్యాకప్ తీసుకుంటోంది', 'దయచేసి కంప్యూటర్ ఆఫ్ చేయవద్దు.'], + saved: ['అన్నీ సేవ్ చేయబడ్డాయి', 'Flo కొద్ది క్షణాల్లో మూసివేయబడుతుంది.'], + }, }; export const RTL_STATUS_LANGUAGES: ReadonlySet = new Set(['ar', 'fa', 'ur']); diff --git a/shared/print/raster-canvas.ts b/shared/print/raster-canvas.ts index 6215ffdba..52b45326d 100644 --- a/shared/print/raster-canvas.ts +++ b/shared/print/raster-canvas.ts @@ -56,7 +56,7 @@ export function paintRasterRequest( const topPad = 3; const weight = styles.includes('bold') ? '700' : '400'; const fontFallback = - '-apple-system, BlinkMacSystemFont, "Segoe UI", "Noto Sans Bengali", "Nirmala UI", "Vrinda", "Bangla Sangam MN", "Noto Sans Devanagari", "Kohinoor Devanagari", "Devanagari Sangam MN", "Noto Sans Gurmukhi", "Raavi", "Kohinoor Gurmukhi", "Gurmukhi Sangam MN", "Noto Sans Thai", "Leelawadee UI", "Thonburi", "PingFang SC", "Microsoft YaHei", "Noto Sans CJK SC", "PingFang TC", "Microsoft JhengHei", "Noto Sans CJK TC", "Noto Sans TC", "Noto Sans", sans-serif'; + '-apple-system, BlinkMacSystemFont, "Segoe UI", "Noto Sans Bengali", "Nirmala UI", "Vrinda", "Bangla Sangam MN", "Noto Sans Devanagari", "Kohinoor Devanagari", "Devanagari Sangam MN", "Noto Sans Gurmukhi", "Raavi", "Kohinoor Gurmukhi", "Gurmukhi Sangam MN", "Noto Sans Telugu", "Kohinoor Telugu", "Telugu Sangam MN", "Noto Sans Thai", "Leelawadee UI", "Thonburi", "PingFang SC", "Microsoft YaHei", "Noto Sans CJK SC", "PingFang TC", "Microsoft JhengHei", "Noto Sans CJK TC", "Noto Sans TC", "Noto Sans", sans-serif'; const fontSpec = request.bundledFont ? JSON.stringify(request.bundledFont.family) + ', ' + fontFallback : fontFallback; @@ -69,7 +69,7 @@ export function paintRasterRequest( return makeFailure('Grapheme segmentation is unavailable'); const segmenter = new Intl.Segmenter(undefined, { granularity: 'grapheme' }); const isIndicVirama = (codePoint: number): boolean => - codePoint === 0x094d || codePoint === 0x09cd || codePoint === 0x0a4d; + codePoint === 0x094d || codePoint === 0x09cd || codePoint === 0x0a4d || codePoint === 0x0c4d; const isIndicConsonant = (codePoint: number): boolean => (codePoint >= 0x0915 && codePoint <= 0x0939) || (codePoint >= 0x0958 && codePoint <= 0x095f) || @@ -80,7 +80,9 @@ export function paintRasterRequest( codePoint === 0x09fc || (codePoint >= 0x0a15 && codePoint <= 0x0a39) || (codePoint >= 0x0a59 && codePoint <= 0x0a5e) || - codePoint === 0x0a75; + codePoint === 0x0a75 || + (codePoint >= 0x0c15 && codePoint <= 0x0c39) || + (codePoint >= 0x0c58 && codePoint <= 0x0c5a); const graphemes = (value: string): string[] => { const merged: string[] = []; for (const { segment } of segmenter.segment(value)) { diff --git a/shared/print/width.ts b/shared/print/width.ts index 28fb9ff61..382edb1c1 100644 --- a/shared/print/width.ts +++ b/shared/print/width.ts @@ -6,7 +6,7 @@ const GRAPHEME_SEGMENTER = ? new Intl.Segmenter('und', { granularity: 'grapheme' }) : null; const THAI_SARA_AM_CODE_POINT = 0x0e33; -const INDIC_VIRAMA_CODE_POINTS = new Set([0x094d, 0x09cd, 0x0a4d]); +const INDIC_VIRAMA_CODE_POINTS = new Set([0x094d, 0x09cd, 0x0a4d, 0x0c4d]); const EMOJI_BASE_RE = /\p{Extended_Pictographic}/u; export type PrintPaperWidth = @@ -75,7 +75,9 @@ function isIndicConsonant(codePoint: number): boolean { codePoint === 0x09fc || (codePoint >= 0x0a15 && codePoint <= 0x0a39) || (codePoint >= 0x0a59 && codePoint <= 0x0a5e) || - codePoint === 0x0a75 + codePoint === 0x0a75 || + (codePoint >= 0x0c15 && codePoint <= 0x0c39) || + (codePoint >= 0x0c58 && codePoint <= 0x0c5a) ); } diff --git a/tests/browser-receipts.test.ts b/tests/browser-receipts.test.ts index 37f39890f..c3dc454eb 100644 --- a/tests/browser-receipts.test.ts +++ b/tests/browser-receipts.test.ts @@ -120,6 +120,7 @@ async function run() { 'mr', 'sw', 'pa', + 'te', ] as const) { await i18n.loadLocaleMessages(lang); } @@ -705,6 +706,27 @@ async function run() { "'Noto Naskh Arabic', 'Noto Sans Bengali', 'Vrinda', 'Bangla Sangam MN', 'Noto Sans Devanagari'", ), ); + + const teHtml = generateBillHtml( + sampleEnBill, + { ...neTenant, currency: 'INR', country: 'IN', timezone: 'Asia/Kolkata' }, + { language: 'te', isReprint: true }, + ); + assert( + 'TE receipt has lang="te-IN" and dir="ltr"', + teHtml.includes(''), + ); + assert( + 'TE receipt declares the Telugu font families', + teHtml.includes("'Noto Sans Telugu', 'Kohinoor Telugu', 'Telugu Sangam MN'"), + ); + assert( + 'TE labels are Telugu', + teHtml.includes('రీప్రింట్') && + teHtml.includes('బిల్లు #') && + teHtml.includes('మొత్తం') && + teHtml.includes('మీ సందర్శనకు ధన్యవాదాలు!'), + ); } console.log('\nTest Suite 6: Canonical semantic labels and unknown-language fallback'); @@ -1142,6 +1164,34 @@ async function run() { swahiliSlip.includes('Jumla Ndogo') && swahiliSlip.includes('Jumla'), ); + + const teluguSlip = generateOrderSlipHtml( + testIranOrder, + { + title: 'ఆర్డర్ స్లిప్', + subtotal: 'ఉప మొత్తం', + discount: 'డిస్కౌంట్', + serviceCharge: 'సర్వీస్ ఛార్జ్', + deliveryCharge: 'డెలివరీ ఛార్జ్', + packagingCharge: 'ప్యాకేజింగ్ ఛార్జ్', + tax: 'పన్ను', + total: 'మొత్తం', + }, + { + country: 'IN', + currency: 'INR', + locale: 'te-IN', + direction: 'ltr', + }, + ); + assert( + 'Telugu order slip carries te-IN LTR metadata and Telugu font fallback', + teluguSlip.includes('lang="te-IN" dir="ltr"') && + teluguSlip.includes('Noto Sans Telugu') && + teluguSlip.includes('ఆర్డర్ స్లిప్') && + teluguSlip.includes('ఉప మొత్తం') && + teluguSlip.includes('మొత్తం'), + ); } console.log( diff --git a/tests/decoupled-ui-locale.test.ts b/tests/decoupled-ui-locale.test.ts index 7371342de..cc84ffc65 100644 --- a/tests/decoupled-ui-locale.test.ts +++ b/tests/decoupled-ui-locale.test.ts @@ -372,6 +372,7 @@ async function runTests() { | 'hi' | 'ne' | 'pa' + | 'te' | 'sq' | 'th' | 'ha' @@ -392,6 +393,7 @@ async function runTests() { { lang: 'hi', label: 'Hindi UI', filePrefix: 'receipt-argentina-hindi-ui' }, { lang: 'ne', label: 'Nepali UI', filePrefix: 'receipt-argentina-nepali-ui' }, { lang: 'pa', label: 'Punjabi UI', filePrefix: 'receipt-argentina-punjabi-ui' }, + { lang: 'te', label: 'Telugu UI', filePrefix: 'receipt-argentina-telugu-ui' }, { lang: 'sq', label: 'Albanian UI', filePrefix: 'receipt-argentina-albanian-ui' }, { lang: 'th', label: 'Thai UI', filePrefix: 'receipt-argentina-thai-ui' }, { lang: 'ha', label: 'Hausa UI', filePrefix: 'receipt-argentina-hausa-ui' }, @@ -490,6 +492,15 @@ async function runTests() { receiptHtml.includes('ਅਗ'), `Receipt in Punjabi UI must contain a Punjabi month name, got: ${receiptHtml}`, ); + } else if (lang === 'te') { + assert.ok( + receiptHtml.includes('బిల్లు #') && receiptHtml.includes('మొత్తం'), + `Receipt in Telugu UI must contain Telugu labels`, + ); + assert.ok( + receiptHtml.includes('ఆగ') || receiptHtml.includes('ఆగస్టు'), + `Receipt in Telugu UI must contain a Telugu month name, got: ${receiptHtml}`, + ); } console.log( diff --git a/tests/i18n-audit-remediations.test.ts b/tests/i18n-audit-remediations.test.ts index 84d9ce251..22b65de2b 100644 --- a/tests/i18n-audit-remediations.test.ts +++ b/tests/i18n-audit-remediations.test.ts @@ -110,6 +110,7 @@ async function run() { 'mr', 'sw', 'pa', + 'te', ] as const) { await ensureReceiptMessagesLoaded(lang); const cached = getCachedMessages(lang); @@ -197,6 +198,7 @@ async function run() { mr: { tag: 'mr-IN', dir: 'ltr' }, sw: { tag: 'sw-KE', dir: 'ltr' }, pa: { tag: 'pa-IN', dir: 'ltr' }, + te: { tag: 'te-IN', dir: 'ltr' }, }; for (const [lang, { tag, dir }] of Object.entries(expectedLocaleTags)) { @@ -444,6 +446,7 @@ async function run() { 'mr', 'sw', 'pa', + 'te', ]) { const filePath = path.join(MESSAGES_DIR, `${lang}.json`); const content = JSON.parse(fs.readFileSync(filePath, 'utf8')); diff --git a/tests/phase3-print-regressions.test.ts b/tests/phase3-print-regressions.test.ts index 1e857b035..9166dad64 100644 --- a/tests/phase3-print-regressions.test.ts +++ b/tests/phase3-print-regressions.test.ts @@ -33,10 +33,12 @@ const languages = [ 'mr', 'sw', 'pa', + 'te', ] as const; -// Any Devanagari codepoint: the native paths must emit none, not merely none of +// Any Devanagari or Telugu codepoint: the native paths must emit none, not merely none of // the specific phrases this fixture happens to use. const DEVANAGARI_RE = /[ऀ-ॿ]/; +const TELUGU_RE = /[\u0C00-\u0C7F]/; const order = { order_number: 'KOT-PHASE3-001', type: 'dine_in', @@ -181,6 +183,18 @@ async function run(): Promise { `${language}: browser KOT carries locale pa-IN`, ); } + if (language === 'te') { + assert.match( + browserHtml, + /font-family:'Noto Sans Telugu'/, + `${language}: browser KOT selects the Telugu font stack`, + ); + assert.match( + browserHtml, + /lang="te-IN" dir="ltr"/, + `${language}: browser KOT must carry its own locale te-IN`, + ); + } assert.match(browserHtml, /KOT-PHASE3-001/, `${language}: browser order number`); assert.match(browserHtml, /Pending coffee/, `${language}: browser pending item`); assert.match(browserHtml, /Oat milk.*x3/, `${language}: browser preserves addon quantity`); @@ -564,6 +578,72 @@ async function run(): Promise { ); } + { + const teluguOrder = { + ...order, + items: [ + { + quantity: 1, + product_name: 'హైదరాబాదీ బిర్యానీ', + status: 'pending', + addons: [{ name: 'పెరుగు', quantity: 1 }], + special_instructions: 'తక్కువ కారం', + }, + ], + }; + const thermalWarnings: any[] = []; + const thermalText = escPosToText( + formatKOT( + teluguOrder, + teluguOrder.items, + 'Main Kitchen', + 42, + false, + 'full', + 'en-US', + { timeZone: 'UTC' }, + thermalWarnings, + false, + 'te', + ), + ); + assert.equal( + thermalWarnings.some((warning) => warning.kind === 'line'), + true, + 'Telugu unsupported KOT lines warn before native output', + ); + assert.doesNotMatch( + thermalText, + TELUGU_RE, + 'Telugu native KOT emits no Telugu codepoints at all', + ); + + const webUsbWarnings: any[] = []; + const webUsbText = Buffer.from( + frontend.kotEncoder.buildKotBytes( + teluguOrder as any, + { + paperWidth: 58, + language: 'te', + stationName: 'Main Kitchen', + locale: 'te-IN', + timezone: 'UTC', + }, + webUsbWarnings, + ), + ).toString('utf8'); + assert.equal( + webUsbWarnings.some((warning) => warning.kind === 'line'), + true, + 'Telugu unsupported WebUSB KOT lines warn before output', + ); + assert.doesNotMatch( + webUsbText, + TELUGU_RE, + 'Telugu WebUSB KOT emits no Telugu codepoints at all', + ); + } + const longKotHtml = frontend.kotWebPrint.generateKotHtml( { ...order, diff --git a/tests/phase7-setup-i18n.test.ts b/tests/phase7-setup-i18n.test.ts index ae2b59c54..d076f1803 100644 --- a/tests/phase7-setup-i18n.test.ts +++ b/tests/phase7-setup-i18n.test.ts @@ -464,6 +464,38 @@ async function run(): Promise { 'Swahili express snack is localized', ); } + if (language === 'te') { + assert.equal( + rows('categories', 'name', "id = 'cat-express-food'")[0].name, + 'ఆహారం', + 'Telugu express category is localized', + ); + assert.equal( + rows('categories', 'name', "id = 'cat-express-beverages'")[0].name, + 'పానీయాలు', + 'Telugu express beverages category is localized', + ); + assert.equal( + rows('products', 'name', "id = 'prod-express-meal'")[0].name, + 'భోజనం', + 'Telugu express meal is localized', + ); + assert.equal( + rows('products', 'name', "id = 'prod-express-tea'")[0].name, + 'టీ', + 'Telugu express tea is localized', + ); + assert.equal( + rows('products', 'name', "id = 'prod-express-coffee'")[0].name, + 'కాఫీ', + 'Telugu express coffee is localized', + ); + assert.equal( + rows('products', 'name', "id = 'prod-express-snack'")[0].name, + 'చిరుతిండి', + 'Telugu express snack is localized', + ); + } seedSetupProfile(db, 'demo', 'finedine', language, 'IN'); const seededCustomers = rows('customers', 'phone, phone_digits, country_code', 'is_active = 1'); @@ -655,6 +687,28 @@ async function run(): Promise { 'Swahili demo customers use Kenya E.164 numbers independent of the selected store country', ); } + if (language === 'te') { + assert.equal(snapshot.category, 'స్టార్టర్లు', 'Telugu demo category is localized'); + assert.equal(snapshot.product, 'పునుగులు', 'Telugu demo product is localized'); + assert.equal( + rows('products', 'name', "id = 'prod-demo-hyderabadi-biryani'")[0].name, + 'హైదరాబాదీ బిర్యానీ', + 'Telugu demo biryani uses Telugu restaurant terminology', + ); + assert.equal(snapshot.manager, 'డెమో మేనేజర్', 'Telugu demo manager is localized'); + assert.equal(snapshot.customer, 'రవి కుమార్', 'Telugu demo customer is localized'); + assert.deepEqual( + rows('customers', 'phone, country_code', "id LIKE 'cust-demo-%' ORDER BY id").map( + (customer) => [customer.phone, customer.country_code], + ), + [ + ['+919876543210', '+91'], + ['+919876543211', '+91'], + ['+919876543212', '+91'], + ], + 'Telugu demo customers use India E.164 numbers', + ); + } if (language === 'hi') { assert.equal(snapshot.category, 'स्टार्टर', 'Hindi demo category is localized'); assert.equal(snapshot.product, 'पनीर टिक्का', 'Hindi demo product is localized'); diff --git a/tests/print-kernel.test.ts b/tests/print-kernel.test.ts index 5cdc3f9a2..c7d32deee 100644 --- a/tests/print-kernel.test.ts +++ b/tests/print-kernel.test.ts @@ -401,6 +401,7 @@ for (const [label, cluster] of [ ['Devanagari', 'क्ष'], ['Bengali', 'ক্ষ'], ['Gurmukhi', 'ਪ੍ਰ'], + ['Telugu', 'క్ష'], ['Thai', 'กำ'], ['Urdu', 'کّ'], ] as const) { @@ -646,6 +647,7 @@ try { String.fromCodePoint(0x0915, 0x094d, 0x0937), String.fromCodePoint(0x0995, 0x09cd, 0x09b7), String.fromCodePoint(0x0a2a, 0x0a4d, 0x0a30), + String.fromCodePoint(0x0c15, 0x0c4d, 0x0c37), String.fromCodePoint(0x0e01, 0x0e33), 'کّ', 'ک\u200c', diff --git a/tests/print-labels.test.ts b/tests/print-labels.test.ts index a7cac93a0..a0abe2c72 100644 --- a/tests/print-labels.test.ts +++ b/tests/print-labels.test.ts @@ -345,6 +345,22 @@ function run(): void { printLabel('pa', 'pos.subtotal') === 'ਉਪ-ਜੋੜ' && printLabel('pa', 'print.grandTotal') !== printLabel('pa', 'pos.subtotal'), ); + assert('Telugu grand total is localized', printLabel('te', 'print.grandTotal') === 'మొత్తం'); + assert( + 'Telugu bill number label is localized', + printLabel('te', 'receipt.billNumber') === 'బిల్లు #', + ); + assert('Telugu print-test amount is localized', printLabel('te', 'printTest.amt') === 'మొత్తం'); + assert( + 'Telugu takeaway is distinct from delivery', + printLabel('te', 'pos.orderTypeTakeaway') === 'టేక్అవే' && + printLabel('te', 'pos.orderTypeDelivery') === 'డెలివరీ', + ); + assert( + 'Telugu subtotal stays distinct from grand total', + printLabel('te', 'pos.subtotal') === 'ఉప మొత్తం' && + printLabel('te', 'print.grandTotal') !== printLabel('te', 'pos.subtotal'), + ); console.log('\n✅ Test 2: classic receipt honors language'); { diff --git a/tests/raster-renderer-electron.test.cjs b/tests/raster-renderer-electron.test.cjs index 65fdd934f..ff8d424d1 100644 --- a/tests/raster-renderer-electron.test.cjs +++ b/tests/raster-renderer-electron.test.cjs @@ -1,12 +1,19 @@ const assert = require('node:assert/strict'); const path = require('node:path'); const { app, BrowserWindow } = require('electron'); -const { ChromiumRasterRenderer, getSharedRasterRenderer, destroySharedRasterRenderer } = require('../dist/main/printers/raster-renderer.js'); +const { + ChromiumRasterRenderer, + getSharedRasterRenderer, + destroySharedRasterRenderer, +} = require('../dist/main/printers/raster-renderer.js'); const font = { family: 'FloRaster', dataUrl: 'data:font/woff2;base64,AA==' }; function area(unit) { - return unit.bands.reduce((total, band) => total + band.pixels.reduce((sum, pixel) => sum + pixel, 0), 0); + return unit.bands.reduce( + (total, band) => total + band.pixels.reduce((sum, pixel) => sum + pixel, 0), + 0, + ); } async function run() { @@ -73,15 +80,27 @@ async function run() { maxLines: 4, bundledFont: font, }; - const normal = await renderer.render({ ...base, requestId: 'electron-normal', style: 'normal' }); + const normal = await renderer.render({ + ...base, + requestId: 'electron-normal', + style: 'normal', + }); const styled = await renderer.render({ ...base, requestId: 'electron-styled', style: 'bold', styles: ['bold', 'double-height', 'double-width'], }); - assert.equal(normal.ok, true, `normal raster failed: ${normal.code ?? 'unknown'} - ${normal.detail ?? 'no detail'}`); - assert.equal(styled.ok, true, `styled raster failed: ${styled.code ?? 'unknown'} - ${styled.detail ?? 'no detail'}`); + assert.equal( + normal.ok, + true, + `normal raster failed: ${normal.code ?? 'unknown'} - ${normal.detail ?? 'no detail'}`, + ); + assert.equal( + styled.ok, + true, + `styled raster failed: ${styled.code ?? 'unknown'} - ${styled.detail ?? 'no detail'}`, + ); const fontCount = await surface.webContents.executeJavaScript('document.fonts.size'); assert.equal(fontCount, 1); assert.equal(normal.unit.complete, true); @@ -190,6 +209,22 @@ async function run() { assert.equal(bengaliRender.unit.complete, true); assert.ok(area(bengaliRender.unit) > 0); + const teluguRender = await renderer.render({ + version: 1, + requestId: 'electron-telugu-system-font', + text: 'తెలుగు', + widthDots: 120, + maxBandHeight: 200, + direction: 'ltr', + align: 'left', + style: 'normal', + financial: true, + maxLines: 4, + }); + assert.equal(teluguRender.ok, true); + assert.equal(teluguRender.unit.complete, true); + assert.ok(area(teluguRender.unit) > 0); + const thaiRender = await renderer.render({ version: 1, requestId: 'electron-thai-system-font', @@ -207,7 +242,10 @@ async function run() { assert.ok(area(thaiRender.unit) > 0); surface.webContents.emit('render-process-gone'); - const processFailure = await renderer.render({ ...base, requestId: 'electron-process-failure' }); + const processFailure = await renderer.render({ + ...base, + requestId: 'electron-process-failure', + }); assert.deepEqual(processFailure, { version: 1, requestId: 'electron-process-failure', diff --git a/tests/reports-whatsapp.test.ts b/tests/reports-whatsapp.test.ts index 74ce64d5e..0d98d7d62 100644 --- a/tests/reports-whatsapp.test.ts +++ b/tests/reports-whatsapp.test.ts @@ -284,7 +284,7 @@ async function main(): Promise { const localeFiles = fs.readdirSync(messageDir).filter((file) => file.endsWith('.json')); assert.equal( localeFiles.length, - 29, + 30, 'the full-report localization test covers all supported locales', ); for (const localeFile of localeFiles) { diff --git a/tests/rtl-dashboard-pos-common.test.ts b/tests/rtl-dashboard-pos-common.test.ts index 43c081bc8..7df8399a6 100644 --- a/tests/rtl-dashboard-pos-common.test.ts +++ b/tests/rtl-dashboard-pos-common.test.ts @@ -371,6 +371,7 @@ function run(): void { 'mr', 'sw', 'pa', + 'te', ] as const) { usePosSettingsStore.getState().setLanguage(ltrLang); const renderedLtr = renderDirectionalToaster(getLanguageLocale(ltrLang)); @@ -482,6 +483,7 @@ function run(): void { 'mr', 'sw', 'pa', + 'te', ] as const) { assert(getLanguageDirection(ltrLang) === 'ltr', `${ltrLang} must resolve to ltr`); } diff --git a/tests/rtl-kds-server-whatsapp.test.ts b/tests/rtl-kds-server-whatsapp.test.ts index ffe5e7cdb..b349ab703 100644 --- a/tests/rtl-kds-server-whatsapp.test.ts +++ b/tests/rtl-kds-server-whatsapp.test.ts @@ -262,6 +262,7 @@ async function run(): Promise { 'mr', 'sw', 'pa', + 'te', ] as const) { await loadLocaleMessages(lang); } @@ -365,6 +366,7 @@ async function run(): Promise { 'mr', 'sw', 'pa', + 'te', ] as const) { usePosSettingsStore.getState().setLanguage(lang); const kdsMarkup = ReactDOMServer.renderToStaticMarkup(React.createElement(KdsHtmlLang)); @@ -406,6 +408,7 @@ async function run(): Promise { 'mr', 'sw', 'pa', + 'te', ] as const) { assert(getLanguageDirection(ltrLang) === 'ltr', `${ltrLang} must resolve to ltr`); } @@ -439,7 +442,8 @@ async function run(): Promise { | 'jv' | 'mr' | 'sw' - | 'pa', + | 'pa' + | 'te', ) => { const messages = getCachedMessages(lang) ?? getCachedMessages('en') ?? {}; return createTranslator({ locale: getLanguageLocale(lang), messages }) as unknown as ( @@ -516,6 +520,7 @@ async function run(): Promise { 'mr', 'sw', 'pa', + 'te', ] as const) { for (const key of [ 'kds.disabledTitle', diff --git a/tests/rtl-setup-auth-settings.test.ts b/tests/rtl-setup-auth-settings.test.ts index 0f7af0370..974cb1702 100644 --- a/tests/rtl-setup-auth-settings.test.ts +++ b/tests/rtl-setup-auth-settings.test.ts @@ -509,6 +509,18 @@ async function run(): Promise { 'pa-Guru-IN must resolve through the Gurmukhi script fallback to pa-IN', ); }); + withNavigatorLanguage('te-IN', () => { + assert( + i18nModule.getBrowserLanguage() === 'te', + 'getBrowserLanguage must return "te" for te-IN', + ); + }); + withNavigatorLanguage('te', () => { + assert( + i18nModule.getBrowserLanguage() === 'te', + 'getBrowserLanguage must return "te" for bare te', + ); + }); withNavigatorLanguage( 'en-US', () => { @@ -564,6 +576,7 @@ async function run(): Promise { 'mr', 'sw', 'pa', + 'te', ] as const; const { createTranslator } = frontendRequire('use-intl/core'); // #375: prime the shared locale cache so messages resolve for all locales. diff --git a/tests/thermal-capabilities.test.ts b/tests/thermal-capabilities.test.ts index b9cbc7f1e..1eaeebd1c 100644 --- a/tests/thermal-capabilities.test.ts +++ b/tests/thermal-capabilities.test.ts @@ -15,11 +15,18 @@ function loadFrontendKotEncoder(): typeof import('../frontend/src/lib/printer/ko const path = require('node:path') as typeof import('node:path'); const moduleApi = require('node:module') as { _resolveFilename: (...args: any[]) => string }; const originalResolveFilename = moduleApi._resolveFilename; - moduleApi._resolveFilename = function (request: string, parent: any, isMain: boolean, options?: any) { + moduleApi._resolveFilename = function ( + request: string, + parent: any, + isMain: boolean, + options?: any, + ) { let resolvedRequest = request; if (request === '@countries') resolvedRequest = path.resolve(__dirname, '../main/countries.ts'); - else if (request.startsWith('@/')) resolvedRequest = path.resolve(__dirname, '../frontend/src', request.slice(2)); - else if (request.startsWith('@print/')) resolvedRequest = path.resolve(__dirname, '../shared/print', request.slice('@print/'.length)); + else if (request.startsWith('@/')) + resolvedRequest = path.resolve(__dirname, '../frontend/src', request.slice(2)); + else if (request.startsWith('@print/')) + resolvedRequest = path.resolve(__dirname, '../shared/print', request.slice('@print/'.length)); return originalResolveFilename.call(this, resolvedRequest, parent, isMain, options); }; try { @@ -35,7 +42,9 @@ const order = { created_at: '2026-08-21 18:42:00', table: { name: '4' }, customer: { name: 'Asha' }, - items: [{ quantity: 1, product_name: 'چای', status: 'pending', addons: [], special_instructions: '' }], + items: [ + { quantity: 1, product_name: 'چای', status: 'pending', addons: [], special_instructions: '' }, + ], }; const latinCodePageCapabilities: ThermalPrinterCapabilities = { @@ -50,33 +59,48 @@ const shapingCapabilities: ThermalPrinterCapabilities = { shaping: { arabic: true }, }; -function outputPair(capabilities: ThermalPrinterCapabilities, arabicShaping: boolean, kotOrder = order, useUnicode = false): { backend: string; webusb: string; backendWarnings: any[]; webusbWarnings: any[] } { +function outputPair( + capabilities: ThermalPrinterCapabilities, + arabicShaping: boolean, + kotOrder = order, + useUnicode = false, +): { backend: string; webusb: string; backendWarnings: any[]; webusbWarnings: any[] } { const backendWarnings: any[] = []; - const backend = escPosToText(formatKOT( - kotOrder, - kotOrder.items, - 'Kitchen', - 42, - useUnicode, - 'full', - 'en-US', - { timeZone: 'UTC' }, - backendWarnings, - arabicShaping, - 'en', - capabilities, - )); + const backend = escPosToText( + formatKOT( + kotOrder, + kotOrder.items, + 'Kitchen', + 42, + useUnicode, + 'full', + 'en-US', + { timeZone: 'UTC' }, + backendWarnings, + arabicShaping, + 'en', + capabilities, + ), + ); const webusbWarnings: any[] = []; const encoder = loadFrontendKotEncoder(); - const webusb = escPosToText(Buffer.from(encoder.buildKotBytes(kotOrder as any, { - paperWidth: 58, - language: 'en', - stationName: 'Kitchen', - locale: 'en-US', - timezone: 'UTC', - arabicShaping, - capabilities, - }, webusbWarnings))); + const webusb = escPosToText( + Buffer.from( + encoder.buildKotBytes( + kotOrder as any, + { + paperWidth: 58, + language: 'en', + stationName: 'Kitchen', + locale: 'en-US', + timezone: 'UTC', + arabicShaping, + capabilities, + }, + webusbWarnings, + ), + ), + ); return { backend, webusb, backendWarnings, webusbWarnings }; } @@ -85,9 +109,17 @@ function run(): void { assert.deepEqual(generic.capabilities.encoding.codePages, ['ascii']); assert.equal(generic.capabilities.warnings.financialText, 'refuse'); assert.equal(normalizeThermalText('Küche', generic.capabilities), 'Kueche'); - assert.equal(isThermalTextRepresentable('Burrito de Camarón 1 $550', generic.capabilities), false); + assert.equal( + isThermalTextRepresentable('Burrito de Camarón 1 $550', generic.capabilities), + false, + ); const genericCamaronWarnings: any[] = []; - const genericCamaronBytes = buildEscPos(['Burrito de Camarón 1 $550'], false, { capabilities: generic.capabilities, financialLineRanges: [{ lineIndex: 0, lineCount: 1 }] }, genericCamaronWarnings); + const genericCamaronBytes = buildEscPos( + ['Burrito de Camarón 1 $550'], + false, + { capabilities: generic.capabilities, financialLineRanges: [{ lineIndex: 0, lineCount: 1 }] }, + genericCamaronWarnings, + ); assert.equal(genericCamaronWarnings.length, 1); assert.equal(genericCamaronWarnings[0].kind, 'financial'); assert.equal(genericCamaronBytes.length, 0); @@ -110,9 +142,35 @@ function run(): void { ); assert.equal(isThermalTextRepresentable('किनारा', generic.capabilities), false); assert.equal(generic.capabilities.raster.font, undefined); - assert.ok(hindiWarnings.some((warning) => warning.text.includes('किनारा')), 'unsupported Devanagari KOT text keeps an explicit warning'); + assert.ok( + hindiWarnings.some((warning) => warning.text.includes('किनारा')), + 'unsupported Devanagari KOT text keeps an explicit warning', + ); assert.equal(escPosToText(hindiBytes).includes('किनारा'), false); + const teluguOrder = { ...order, items: [{ ...order.items[0], product_name: 'బిర్యానీ' }] }; + const teluguWarnings: any[] = []; + const teluguBytes = formatKOT( + teluguOrder, + teluguOrder.items, + 'Kitchen', + 42, + false, + 'full', + 'te-IN', + { timeZone: 'UTC' }, + teluguWarnings, + false, + 'te', + generic.capabilities, + ); + assert.equal(isThermalTextRepresentable('బిర్యానీ', generic.capabilities), false); + assert.ok( + teluguWarnings.some((warning) => warning.text.includes('బిర్యానీ')), + 'unsupported Telugu KOT text keeps an explicit warning', + ); + assert.equal(escPosToText(teluguBytes).includes('బిర్యానీ'), false); + const epson = resolvePrinterProfile({ profile_id: 'epson-tm-series' }); const xprinter = resolvePrinterProfile({ profile_id: 'xprinter-xp-v320m-v330m' }); assert.equal(epson.capabilities.representability.scripts.includes('latin'), true); @@ -120,7 +178,12 @@ function run(): void { assert.equal(isThermalTextRepresentable('Burrito de Camarón 1 $550', epson.capabilities), true); assert.equal(selectThermalCodePage('Burrito de Camarón', epson.capabilities), 'cp437'); const epsonCamaronWarnings: any[] = []; - const epsonCamaronBytes = buildEscPos(['{INIT}', 'Burrito de Camarón 1 $550'], false, { capabilities: epson.capabilities, financialLineRanges: [{ lineIndex: 1, lineCount: 1 }] }, epsonCamaronWarnings); + const epsonCamaronBytes = buildEscPos( + ['{INIT}', 'Burrito de Camarón 1 $550'], + false, + { capabilities: epson.capabilities, financialLineRanges: [{ lineIndex: 1, lineCount: 1 }] }, + epsonCamaronWarnings, + ); assert.deepEqual(epsonCamaronWarnings, []); assert.ok(epsonCamaronBytes.length > 0); assert.equal(escPosToText(epsonCamaronBytes).includes('Burrito de Camarón'), true); @@ -129,7 +192,9 @@ function run(): void { assert.equal(normalizeThermalText('Straße', epson.capabilities), 'Straße'); assert.equal(selectThermalCodePage('Küche', epson.capabilities), 'cp437'); assert.equal(selectThermalCodePage('Straße', epson.capabilities), 'cp437'); - const epsonKuecheBytes = buildEscPos(['{INIT}', 'Küche Straße'], false, { capabilities: epson.capabilities }); + const epsonKuecheBytes = buildEscPos(['{INIT}', 'Küche Straße'], false, { + capabilities: epson.capabilities, + }); assert.equal(escPosToText(epsonKuecheBytes).includes('Küche Straße'), true); assert.equal(selectThermalCodePage('Cafe', latinCodePageCapabilities), 'cp437'); @@ -140,11 +205,16 @@ function run(): void { assert.equal(isThermalTextRepresentable('π', latinCodePageCapabilities), false); assert.equal(isThermalTextRepresentable('עברית', latinCodePageCapabilities), false); const greekWarnings: any[] = []; - const greekBytes = buildEscPos(['π'], false, { capabilities: latinCodePageCapabilities }, greekWarnings); + const greekBytes = buildEscPos( + ['π'], + false, + { capabilities: latinCodePageCapabilities }, + greekWarnings, + ); assert.equal(escPosToText(greekBytes).includes('π'), false); assert.equal(greekWarnings.length, 1); const codePageBytes = buildEscPos(['À'], false, { capabilities: latinCodePageCapabilities }); - assert.equal(codePageBytes.includes(Buffer.from([0x1B, 0x74, 2])), true); + assert.equal(codePageBytes.includes(Buffer.from([0x1b, 0x74, 2])), true); const latinOrder = { ...order, @@ -166,15 +236,19 @@ function run(): void { latinCodePageCapabilities, ); const latinWebUsbWarnings: any[] = []; - const latinWebUsbBytes = loadFrontendKotEncoder().buildKotBytes(latinOrder as any, { - paperWidth: 58, - language: 'en', - stationName: 'Kitchen', - locale: 'en-US', - timezone: 'UTC', - capabilities: latinCodePageCapabilities, - }, latinWebUsbWarnings); - const cp850Command = Buffer.from([0x1B, 0x74, escPosCodePageId('cp850')]); + const latinWebUsbBytes = loadFrontendKotEncoder().buildKotBytes( + latinOrder as any, + { + paperWidth: 58, + language: 'en', + stationName: 'Kitchen', + locale: 'en-US', + timezone: 'UTC', + capabilities: latinCodePageCapabilities, + }, + latinWebUsbWarnings, + ); + const cp850Command = Buffer.from([0x1b, 0x74, escPosCodePageId('cp850')]); assert.equal(selectThermalCodePage('Smørrebrød', latinCodePageCapabilities), 'cp850'); assert.equal(Buffer.from(latinBackendBytes).includes(cp850Command), true); assert.equal(Buffer.from(latinWebUsbBytes).includes(cp850Command), true); @@ -195,8 +269,14 @@ function run(): void { const shapedPair = outputPair(shapingCapabilities, true); assert.match(shapedPair.backend, /چای/); assert.match(shapedPair.webusb, /چای/); - assert.equal(shapedPair.backendWarnings.some((warning) => warning.text.includes('چای')), false); - assert.equal(shapedPair.webusbWarnings.some((warning) => warning.text.includes('چای')), false); + assert.equal( + shapedPair.backendWarnings.some((warning) => warning.text.includes('چای')), + false, + ); + assert.equal( + shapedPair.webusbWarnings.some((warning) => warning.text.includes('چای')), + false, + ); const urduOrder = { ...order, items: [{ ...order.items[0], product_name: 'پنیر ٹکّا' }] }; const urduGenericPair = outputPair(GENERIC_THERMAL_CAPABILITIES, false, urduOrder); @@ -207,8 +287,14 @@ function run(): void { const urduShapedPair = outputPair(shapingCapabilities, true, urduOrder); assert.match(urduShapedPair.backend, /پنیر ٹکّا/); assert.match(urduShapedPair.webusb, /پنیر ٹکّا/); - assert.equal(urduShapedPair.backendWarnings.some((warning) => warning.text.includes('پنیر ٹکّا')), false); - assert.equal(urduShapedPair.webusbWarnings.some((warning) => warning.text.includes('پنیر ٹکّا')), false); + assert.equal( + urduShapedPair.backendWarnings.some((warning) => warning.text.includes('پنیر ٹکّا')), + false, + ); + assert.equal( + urduShapedPair.webusbWarnings.some((warning) => warning.text.includes('پنیر ٹکّا')), + false, + ); console.log('Thermal capability parity: backend and WebUSB fixtures passed.'); } diff --git a/tests/translations.test.ts b/tests/translations.test.ts index db6d72d04..1d53d8b24 100644 --- a/tests/translations.test.ts +++ b/tests/translations.test.ts @@ -77,6 +77,9 @@ * 28. Punjabi safeguards: pa.json values never contain placeholders, malformed * replacement characters, or non-NFC text, and only documented shared * values may remain identical to English. + * 29. Telugu safeguards: te.json values never contain placeholders, malformed + * replacement characters, invisible formatting characters, or non-NFC text, + * and only documented shared values may remain identical to English. * * Negative tests at the bottom feed broken fixture data into each validator * and assert it is caught, so a regression in the validators themselves @@ -2740,6 +2743,84 @@ function paFallbackErrors( return errors; } +/** Telugu translation safeguards, including canonical NFC text and script checks. */ +const TE_INTENTIONAL_IDENTICAL = new Set([ + 'auth.emailPlaceholder', // example email placeholder + 'common.appTitle', // brand name + 'common.brandName', // brand name + 'common.logoAlt', // brand name + 'dashboard.exportCsv', // file format label + 'dashboard.exportPdf', // file format label + 'dashboard.exportXlsx', // file format label + 'dashboard.ticketMethodCount', // pure format: {count} × + 'kds.emptyColumn', // em dash + 'nav.kds', // technical acronym + 'nav.pos', // technical acronym + 'nav.whatsapp', // brand name + 'pos.addonPrice', // pure format: +{currency}{price} + 'pos.loadingEllipsis', // ellipsis + 'pos.tagCount', // pure format: {tag} ×{count} + 'pos.taxLine', // pure format: {title} @{rate}% + 'printTest.escpos', // technical acronym + 'printTest.paperWidth58', // paper size specification + 'printTest.paperWidth80', // paper size specification + 'print.hsn', // GST HSN technical acronym + 'print.zReport.paymentCount', // pure format: x{count} + 'products.addonSelectionRange', // pure format: {min} – {max} + 'products.fieldSku', // technical acronym + 'products.skuLabel', // pure format: SKU: {sku} + 'serverApp.emailPlaceholder', // example email placeholder + 'settings.apiKeyInputPlaceholder', // example API key placeholder + 'settings.connectionUsb', // technical acronym + 'settings.instagramPlaceholder', // example handle placeholder + 'settings.ipAddressPlaceholder', // example IP placeholder + 'settings.kds', // technical acronym + 'settings.languageEn', // native language name + 'settings.languageEs', // native language name + 'settings.languagePt', // native language name + 'settings.paperSize58', // paper size specification + 'settings.paperSize80', // paper size specification + 'settings.paymentMethodUpi', // Indian payment rail acronym + 'settings.portPlaceholder', // example TCP port placeholder + 'settings.registrationEmailPlaceholder', // example email placeholder + 'settings.registrationLastError', // pure placeholder: {error} + 'settings.revflo', // brand name + 'settings.tabOrderflow', // brand name + 'settings.tabWhatsapp', // brand name + 'settings.whatsapp', // brand name + 'setup.ownerEmailPlaceholder', // example email placeholder + 'setup.qsrLabel', // industry acronym + 'tax.auditCreateOverride', // pure format: {entityType} {entityId} → {categoryId} + 'tax.auditUpdateOverride', // pure format: {entityType} {entityId}: {before} → {after} + 'update.downloadingBadge', // pure format: ↓ {percent}% + 'whatsapp.connect.pairingPhonePlaceholder', // pure format: {dialCode}XXXXXXXXXX +]); + +function teFallbackErrors( + teFlat: Record, + enFlat: Record, +): string[] { + const errors: string[] = []; + for (const k of Object.keys(enFlat)) { + const teVal = teFlat[k]; + if (teVal === undefined) continue; + if (teVal.startsWith('[TE]') || teVal.startsWith('[TODO]')) { + errors.push(`te.json ${k} — placeholder prefix found: "${teVal}"`); + } else if (teVal === enFlat[k] && !TE_INTENTIONAL_IDENTICAL.has(k)) { + errors.push( + `te.json ${k} — identical to English value (renders as English for Telugu users)`, + ); + } else if (teVal !== teVal.normalize('NFC')) { + errors.push(`te.json ${k} — value must use Unicode NFC`); + } else if (teVal.includes('\uFFFD')) { + errors.push(`te.json ${k} — value contains a Unicode replacement character`); + } else if (/[\u200B\u200C\u200D\u00AD\uFEFF]/u.test(teVal)) { + errors.push(`te.json ${k} — invisible formatting character found`); + } + } + return errors; +} + /** Keys whose `{number}` placeholder names an order number that must stay * introduced by punctuation (for example `#` or `№`) or a space, never welded * onto the end of a verb-final clause. */ @@ -3796,7 +3877,57 @@ async function run(): Promise { ` ✓ no untranslated pa.json values (${PA_INTENTIONAL_IDENTICAL.size} intentional shared values; NFC verified)`, ); - // 29. No locale may weld an order number onto a word. Devanagari, Arabic, and + // 29. te.json values must be complete, NFC text without malformed or invisible characters. + const teMessages = loadedStrings.get('te'); + if (!teMessages) throw new Error('languages registry must include the maintained te locale'); + const teErrors = teFallbackErrors(teMessages, loadedStrings.get('en')!); + if (teErrors.length) { + console.error(`\nte.json values with errors (${teErrors.length}):`); + for (const e of teErrors.slice(0, 100)) console.error(` - ${e}`); + assert( + false, + 'te.json contains untranslated, placeholder, non-NFC, replacement-character, or invisible values', + ); + } + assert( + teMessages['receipt.cashReceived'] === 'స్వీకరించిన నగదు', + 'te.json receipt.cashReceived must preserve the canonical cash-received label', + ); + assert( + teMessages['pos.tagVeg'] === 'శాకాహారం' && teMessages['products.tagVeg'] === 'శాకాహారం', + 'te.json vegetarian product tags must use the vegetarian Telugu term', + ); + assert( + teMessages['pos.tagNonVeg'] === 'మాంసాహారం' && teMessages['products.tagNonVeg'] === 'మాంసాహారం', + 'te.json non-vegetarian product tags must use the non-vegetarian Telugu term', + ); + assert( + teMessages['orders.takeaway'] === teMessages['pos.orderTypeTakeaway'], + 'te.json takeaway labels must match across orders and POS', + ); + assert( + teMessages['dashboard.payIn'] === 'నగదు జమ' && + teMessages['dashboard.payOut'] === 'నగదు ఉపసంహరణ', + 'te.json cash-movement labels must match the Z-report terminology', + ); + assert( + teMessages['print.zReport.payIn'] === teMessages['dashboard.payIn'] && + teMessages['print.zReport.payOut'] === teMessages['dashboard.payOut'], + 'te.json cash-movement labels must be identical on the dashboard and the Z-report', + ); + assert( + teMessages['pos.addingItemsToOrder'] === 'ఆర్డర్ #{number} కు ఐటెమ్లు జోడించబడుతున్నాయి', + 'te.json addingItemsToOrder must place the order number directly after the # marker', + ); + assert( + teMessages['pos.itemsAddedToOrder'] === 'ఆర్డర్ #{number} కు ఐటెమ్లు జోడించబడ్డాయి', + 'te.json itemsAddedToOrder must place the order number directly after the # marker', + ); + console.log( + ` ✓ no untranslated te.json values (${TE_INTENTIONAL_IDENTICAL.size} intentional shared values; NFC verified)`, + ); + + // 30. No locale may weld an order number onto a word. Devanagari, Arabic, and // Cyrillic are all verb-final, so a trailing "{number}" reads as part of the // word. This covers every registered locale, not only Nepali. const orderNumberErrors = orderNumberPlaceholderErrors(Object.fromEntries(loadedStrings)); @@ -4204,6 +4335,22 @@ function runNegativeTests(): void { 'sw: Unicode replacement character', swFallbackErrors({ 'a.b': 'Kahawa\uFFFD' }, { 'a.b': 'Kahawa' }), ); + expectDetected( + 'te: English-identical value', + teFallbackErrors({ 'a.b': 'Same value' }, { 'a.b': 'Same value' }), + ); + expectDetected( + 'te: placeholder prefix value', + teFallbackErrors({ 'a.b': '[TE] Placeholder value' }, { 'a.b': 'Different value' }), + ); + expectDetected( + 'te: Unicode replacement character', + teFallbackErrors({ 'a.b': 'కా\uFFFDఫీ' }, { 'a.b': 'కాఫీ' }), + ); + expectDetected( + 'te: invisible formatting character', + teFallbackErrors({ 'a.b': 'కా\u200bఫీ' }, { 'a.b': 'కాఫీ' }), + ); expectDetected( 'ne: Unicode replacement character', neFallbackErrors({ 'a.b': 'क��ा' }, { 'a.b': 'काफी' }), @@ -4289,8 +4436,12 @@ function runNegativeTests(): void { 'pos.addingItemsToOrder': 'در حال افزودن کالاها به سفارش شماره {number}', 'pos.itemsAddedToOrder': 'کالاها به سفارش شماره {number} افزوده شدند', }, + te: { + 'pos.addingItemsToOrder': 'ఆర్డర్ #{number} కు ఐటెమ్లు జోడించబడుతున్నాయి', + 'pos.itemsAddedToOrder': 'ఆర్డర్ #{number} కు ఐటెమ్లు జోడించబడ్డాయి', + }, }).length === 0, - 'order-number validator must not flag healthy English, Nepali, Russian, or Persian values', + 'order-number validator must not flag healthy English, Nepali, Russian, Persian, or Telugu values', ); // 8. TypeScript key safety.