diff --git a/.github/workflows/chromatic.yml b/.github/workflows/chromatic.yml index 6d1f08370f..39ce5483ff 100644 --- a/.github/workflows/chromatic.yml +++ b/.github/workflows/chromatic.yml @@ -8,22 +8,25 @@ on: jobs: chromatic-deployment: runs-on: ubuntu-latest - container: node:22.21 defaults: run: working-directory: packages/webapp steps: - name: Checkout repo - uses: actions/checkout@v4 + uses: actions/checkout@v6 with: fetch-depth: 0 + - uses: actions/setup-node@v6 + with: + node-version: 22.21 - name: Setup pnpm - uses: pnpm/action-setup@v4 + uses: pnpm/action-setup@v6 with: - package_json_file: "packages/webapp/package.json" + package_json_file: packages/webapp/package.json - name: Install dependencies - run: pnpm install - - name: Publish to Chromatic - env: - NODE_OPTIONS: "--max-old-space-size=8192" - run: ./node_modules/.bin/chromatic --project-token ${{ secrets.CHROMATIC_PROJECT_TOKEN }} + run: pnpm install --frozen-lockfile + - name: Run Chromatic + uses: chromaui/action@98132da0fca2211fb41b3af7b49ce85176007851 # v17.8.0 + with: + projectToken: ${{ secrets.CHROMATIC_PROJECT_TOKEN }} + workingDir: packages/webapp diff --git a/packages/api/db/migration/20260625000000_generalize_survey_tables.js b/packages/api/db/migration/20260625000000_generalize_survey_tables.js new file mode 100644 index 0000000000..4b5b4e592b --- /dev/null +++ b/packages/api/db/migration/20260625000000_generalize_survey_tables.js @@ -0,0 +1,76 @@ +/* + * Copyright 2026 LiteFarm.org + * This file is part of LiteFarm. + * + * LiteFarm is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * LiteFarm is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details, see . + */ + +/** + * Generalizes the bespoke TAPE survey storage into a reusable, multi-survey model: + * - Renames `tape_survey` to `survey_response` and adds a `survey_key` column identifying which survey each row answers + * - Makes `survey_step` nullable, as it is TAPE-specific and not used by every survey + * - Repurposes the TAPE permissions to generic survey_response permissions (add/get/edit). + * + * @param { import("knex").Knex } knex + * @returns { Promise } + */ +export const up = async function (knex) { + await knex.schema.renameTable('tape_survey', 'survey_response'); + + await knex.schema.alterTable('survey_response', function (table) { + table.string('survey_key').nullable(); + }); + + // Every existing row is a TAPE response. + await knex('survey_response').update({ survey_key: 'tape' }); + await knex.schema.alterTable('survey_response', function (table) { + table.string('survey_key').notNullable().alter(); + }); + + await knex.schema.alterTable('survey_response', function (table) { + table.string('survey_step').nullable().alter(); + }); + + // Repurpose the TAPE permissions (names only) + await knex('permissions') + .where({ permission_id: 185 }) + .update({ name: 'add:survey_response', description: 'add survey_response' }); + await knex('permissions') + .where({ permission_id: 186 }) + .update({ name: 'get:survey_response', description: 'get survey_response' }); + await knex('permissions') + .where({ permission_id: 187 }) + .update({ name: 'edit:survey_response', description: 'edit survey_response' }); +}; + +/** + * @param { import("knex").Knex } knex + * @returns { Promise } + */ +export const down = async function (knex) { + await knex('permissions') + .where({ permission_id: 185 }) + .update({ name: 'add:tape_survey', description: 'add tape_survey' }); + await knex('permissions') + .where({ permission_id: 186 }) + .update({ name: 'get:tape_survey', description: 'get tape_survey' }); + await knex('permissions') + .where({ permission_id: 187 }) + .update({ name: 'edit:tape_survey', description: 'edit tape_survey' }); + + await knex.schema.alterTable('survey_response', function (table) { + table.string('survey_step').notNullable().alter(); + }); + await knex.schema.alterTable('survey_response', function (table) { + table.dropColumn('survey_key'); + }); + await knex.schema.renameTable('survey_response', 'tape_survey'); +}; diff --git a/packages/api/package-lock.json b/packages/api/package-lock.json index 5e16303f02..e7281c5ff7 100644 --- a/packages/api/package-lock.json +++ b/packages/api/package-lock.json @@ -1,12 +1,12 @@ { "name": "litefarm-api", - "version": "3.12.0", + "version": "3.12.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "litefarm-api", - "version": "3.12.0", + "version": "3.12.1", "dependencies": { "@aws-sdk/client-s3": "^3.994.0", "@datafoodconsortium/connector": "^1.0.0-alpha.10", diff --git a/packages/api/package.json b/packages/api/package.json index 65f5a168a2..ce6774e796 100644 --- a/packages/api/package.json +++ b/packages/api/package.json @@ -1,6 +1,6 @@ { "name": "litefarm-api", - "version": "3.12.0", + "version": "3.12.1", "description": "LiteFarm API server", "main": "./api/src/server.js", "type": "module", diff --git a/packages/api/src/controllers/surveyResponseController.ts b/packages/api/src/controllers/surveyResponseController.ts new file mode 100644 index 0000000000..1672de1103 --- /dev/null +++ b/packages/api/src/controllers/surveyResponseController.ts @@ -0,0 +1,149 @@ +/* + * Copyright 2026 LiteFarm.org + * This file is part of LiteFarm. + * + * LiteFarm is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * LiteFarm is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details, see . + */ + +import { Response } from 'express'; +import { LiteFarmRequest } from '../types.js'; +import SurveyResponseModel from '../models/surveyResponseModel.js'; + +interface SurveyResponseData { + survey_version: string; + project_id: string; + survey_step?: string; + [key: string]: unknown; +} + +interface CreateSurveyResponseReqBody { + survey_key: string; + survey_response: SurveyResponseData; +} + +interface LatestSurveyResponseQuery { + survey_key?: string; +} + +interface UpdateSurveyResponseParams { + submission_id: string; +} + +interface UpdateSurveyResponseReqBody { + survey_response: SurveyResponseData; +} + +type InsertableQuery = { insert: (data: Record) => Promise }; + +const surveyResponseController = { + createSurveyResponse() { + return async ( + req: LiteFarmRequest, + res: Response, + ) => { + try { + const { farm_id } = req.headers; + const user_id = req.auth?.user_id; + const { survey_key, survey_response } = req.body; + if (!survey_key) { + return res.status(400).json({ error: 'survey_key is required' }); + } + const { survey_version, project_id, survey_step } = survey_response; + + const insertQuery = SurveyResponseModel.query().context({ + user_id, + }) as unknown as InsertableQuery; + await insertQuery.insert({ + farm_id, + survey_key, + survey_response, + survey_version, + project_id, + survey_step, + }); + + return res.status(201).send(); + } catch (error) { + console.error(error); + return res.status(500).json({ error }); + } + }; + }, + + getLatestSurveyResponse() { + return async (req: LiteFarmRequest, res: Response) => { + try { + const { farm_id } = req.headers; + const { survey_key } = req.query; + if (!survey_key) { + return res.status(400).json({ error: 'survey_key is required' }); + } + // Find the latest survey response of this kind for the farm + const result = await SurveyResponseModel.query() + .where({ farm_id, survey_key }) + .orderBy('created_at', 'desc') + .first(); + return res.status(200).send(result ?? null); + } catch (error) { + console.error(error); + return res.status(500).json({ error }); + } + }; + }, + + // Note: Not currently called from frontend + updateSurveyResponse() { + return async ( + req: LiteFarmRequest< + unknown, + UpdateSurveyResponseParams, + unknown, + UpdateSurveyResponseReqBody + >, + res: Response, + ) => { + try { + const { farm_id } = req.headers; + const user_id = req.auth?.user_id; + const { submission_id } = req.params; + const { survey_response } = req.body; + const { survey_version, project_id, survey_step } = survey_response; + + const existing = (await SurveyResponseModel.query().findOne({ submission_id })) as + | { survey_key: string } + | undefined; + if (!existing) { + return res.status(404).json({ error: 'Survey response not found' }); + } + + const insertQuery = SurveyResponseModel.query().context({ + user_id, + }) as unknown as InsertableQuery; + await insertQuery.insert({ + submission_id, + farm_id, + survey_key: existing.survey_key, + survey_response, + survey_version, + project_id, + survey_step, + }); + + return res.status(204).send(); + } catch (error) { + console.error(error); + return res.status(500).json({ error }); + } + }; + }, +}; + +export default surveyResponseController; diff --git a/packages/api/src/controllers/tapeSurveyController.js b/packages/api/src/controllers/tapeSurveyController.js deleted file mode 100644 index 85e0966dbd..0000000000 --- a/packages/api/src/controllers/tapeSurveyController.js +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright 2026 LiteFarm.org - * This file is part of LiteFarm. - * - * LiteFarm is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * LiteFarm is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details, see . - */ - -import TapeSurveyModel from '../models/tapeSurveyModel.js'; - -const tapeSurveyController = { - createTapeSurvey() { - return async (req, res) => { - try { - const { farm_id } = req.headers; - const { user_id } = req.auth; - const { survey_response } = req.body; - const { survey_version, project_id, survey_step } = survey_response; - - await TapeSurveyModel.query() - .context({ user_id }) - .insert({ farm_id, survey_response, survey_version, project_id, survey_step }); - - return res.status(201).send(); - } catch (error) { - console.error(error); - return res.status(500).json({ error }); - } - }; - }, - - getTapeSurvey() { - return async (req, res) => { - try { - const { farm_id } = req.headers; - // Find the latest tape survey for the farm - const result = await TapeSurveyModel.query() - .where({ farm_id }) - .orderBy('created_at', 'desc') - .first(); - if (!result) { - return res.status(404).json({ error: 'Tape survey not found' }); - } - return res.status(200).send(result); - } catch (error) { - console.error(error); - return res.status(500).json({ error }); - } - }; - }, - - updateTapeSurvey() { - return async (req, res) => { - try { - const { submission_id } = req.params; - if (!submission_id) { - return res.status(400).json({ error: 'submission_id is required' }); - } - const { farm_id } = req.headers; - const { user_id } = req.auth; - const { survey_response } = req.body; - const { survey_version, project_id, survey_step } = survey_response; - await TapeSurveyModel.query().context({ user_id }).insert({ - submission_id, - farm_id, - survey_response, - survey_version, - project_id, - survey_step, - }); - return res.status(204).send(); - } catch (error) { - console.error(error); - return res.status(500).json({ error }); - } - }; - }, -}; - -export default tapeSurveyController; diff --git a/packages/api/src/controllers/timeNotificationController.js b/packages/api/src/controllers/timeNotificationController.js index 7382c58b47..d0dab7be27 100644 --- a/packages/api/src/controllers/timeNotificationController.js +++ b/packages/api/src/controllers/timeNotificationController.js @@ -135,7 +135,10 @@ const timeNotificationController = { ); for (const locationId in prescriptionsByLocation) { - const latestPrescription = prescriptionsByLocation[locationId].at(-1); + // Select the latest prescription explicitly rather than relying on the order Ensemble returns. + const latestPrescription = prescriptionsByLocation[locationId].reduce((latest, current) => + current.id > latest.id ? current : latest, + ); const { id: irrigation_prescription_id, recommended_start_date } = latestPrescription; const previousNotification = await NotificationModel.query() diff --git a/packages/api/src/jobs/locales/km/translation.json b/packages/api/src/jobs/locales/km/translation.json new file mode 100644 index 0000000000..cb93e63f4e --- /dev/null +++ b/packages/api/src/jobs/locales/km/translation.json @@ -0,0 +1,102 @@ +{ + "EXPORT_README_TITLE": "ការយល់ដឹងអំពីការនាំចេញវិញ្ញាបនបត្ររបស់អ្នក", + "N": "អាសូត", + "N/A": "មិនមានទិន្នន័យ", + "NO": "ទេ", + "NOT_SURE": "មិនប្រាកដ", + "OPERATION_NAME": "ឈ្មោះប្រតិបត្តិការ", + "RECORD_A": { + "ACRES": "ឯកតាវាស់ផ្ទៃដីជាអេករ៍", + "AREA": "តំបន់", + "BUILDING": "(អគារ, ព្រៃឈើ, តំបន់ជីវចម្រុ, ផ្លូវបើកបរ)", + "CERTIFIED": "បានបញ្ជាក់", + "CROPS_OR_ANIMALS": "ប្រភេទដំណាំ ឬប្រភេទសត្វក្នុងមួយឯកតា", + "CURRENT_STATUS": "ស្ថានភាពបច្ចុប្បន្ន - សម្គាល់មួយសម្រាប់ក្នុងមួយឯកតា", + "EXPORT_DOCUMENT_NAME": "កំណត់ត្រា អេ", + "HEADER": "កំណត់ត្រា អេ - ការកំណត់អត្តសញ្ញាណទីតាំង", + "HECTARES": "ហិចតា", + "INDIVIDUAL_PRODUCTION_UNIT": "សម្រាប់ឯកតាផលិតកម្មនីមួយៗ (ឧ. ទីតាំង/វាលដី/ផ្ទះកញ្ចក់/តំបន់កំណត់—អាស្រ័យលើប្រតិបត្តិការរបស់អ្នក និងបានដាក់ស្លាកនៅលើផែនទីរបស់អ្នក)", + "NAME_OR_ID": "ឈ្មោះ ឬលេខសម្គាល់​", + "NEW": "ថ្មី", + "NEW_AREA": "ផ្ទៃដី (ដែលបានបន្ថែមក្នុងឆ្នាំនេះ)", + "NON_ORGANIC": "ផ្ទៃដីមិនមែនសរីរាង្គ ក្នុង", + "NON_PRODUCING": "មិនមានផលិតកម្ម", + "OPERATION_NAME": "ឈ្មោះប្រតិបត្តិការ", + "ORGANIC_AREA": "ផ្ទៃដីសរីរាង្គ", + "PLEASE_VERIFY": "សូមពិនិត្យ និងផ្ទៀងផ្ទាត់ព័ត៌មានលម្អិត ហើយធ្វើការកែប្រែប្រសិនបើចាំបាច់រៀងរាល់ឆ្នាំ។ ប្រសិនបើប្រតិបត្តិការមានទីតាំងច្រើនដាច់ដោយឡែក សូមពណ៌នាអំពីទីតាំងនីមួយៗដោយឡែកពីគ្នា។ សូមយោងទៅកាន់ផ្ទាំងគំរូខាងក្រោម សម្រាប់ឧទាហរណ៍អំពីរបៀបបំពេញទម្រង់នេះ។", + "PRODUCTION": "ផលិតផល", + "REMOVED": "លុបពីកម្មវិធី", + "REPORTING_PERIOD": "រយៈពេលរាយការណ៍", + "ROW_FT": "ជួរ ហ្វីត", + "ROW_M": "ជួរ​ ម៉ែត្រ", + "SIZE_IN_PREFERRED_UNIT": "ទំហំក្នុងឯកតាវាស់ដែលបានជ្រើសរើស", + "SPLIT": "បំបែក / ដំណើរការដាច់ដោយឡែកស្របគ្នា", + "SQ_FT": "ហ្វីតការ៉េ", + "SQ_M": "ម៉ែត្រការ៉េ", + "TRANSITIONAL": "អន្តរកាល", + "WHY_REMOVED": "មូលហេតុដែលបានលុបចេញ ឬកំណត់សម្គាល់ផ្សេងៗ" + }, + "RECORD_D": { + "DATE_COMPLETED": "កាលបរិច្ឆេទបញ្ចប់", + "EXPORT_DOCUMENT_NAME": "កំណត់ត្រា D", + "FROM": "ពី", + "HEADER": "កំណត់ត្រា D - គ្រាប់ពូជ និងសម្ភារៈដាំដុះ", + "NOTE": { + "LIST_ALL": "រាយបញ្ជីគ្រាប់ពូជ និងសម្ភារៈដាំដុះទាំងអស់ដែលបានប្រើក្នុងរយៈពេលរាយការណ៍។ សូមចំណាំថា៖", + "ONE": "ត្រូវធានាថា បង្កាន់ដៃទិញ ស្លាក ស្លាកសញ្ញា និងវិញ្ញាបនបត្រសរីរាង្គសម្រាប់គ្រាប់ពូជ/សម្ភារៈដាំដុះទាំងអស់ មានសម្រាប់ត្រួតពិនិត្យក្នុងអំឡុងពេលការត្រួតពិនិត្យ។", + "TWO": { + "A": "ការស្វែងរកភាពមានលក់ជាសាធារណៈតាមស្តង់ដារ សុីអូអែស 5.3 – (កំណត់ត្រា ឌី1 ឬសមមូល)", + "B": "ឯកសារបញ្ជាក់ស្ថានភាពមិនមែនកែប្រែហ្សែន", + "C": "ឯកសារបញ្ជាក់ថា ការព្យាបាលណាមួយ ដូចជា សារធាតុបន្ថែមលើគ្រាប់ពូជ ឬការលាបស្រទាប់លើគ្រាប់ពូជ ត្រូវអនុលោមតាមបញ្ជីសារធាតុអនុញ្ញាត​ ភីអែសអិល (ចំណាំថា ការអនុលោមតាម ស្តង់ដារ​ អិនអូភី មិនគ្រប់គ្រាន់ទេ)", + "PART_1": "ទីណា", + "PART_2": "គ្រាប់ពូជ/សម្ភារៈដាំដុះមិនមែនសរីរាង្គ", + "PART_3": "ប្រសិនបើបានប្រើប្រាស់ ឯកសារខាងក្រោមត្រូវតែមានសម្រាប់បង្ហាញក្នុងអំឡុងពេលត្រួតពិនិត្យ" + } + }, + "REPORTING_PERIOD": "រយៈពេលរាយការណ៍", + "TABLE_COLUMN": { + "IS_SEARCH_COMPLETED": "ប្រសិនបើគ្រាប់ពូជ/សម្ភារៈដាំមិនមែនសរីរាង្គ តើបានធ្វើការស្រាវជ្រាវ/ស្វែងរកហើយឬនៅ (បាទ/ចាស ឬ ទេ)", + "LIST_SEED_TREATMENTS": "រាយបញ្ជីការព្យាបាលគ្រាប់ពូជ (បើមាន)", + "LOT_NUMBER": "លេខផលិត (បើមាន)", + "NON_GE_DOCS_AVAILABLE": "ឯកសារបញ្ជាក់ថាមិនមែនកែប្រែហ្សែន មានឬអត់? (បាទ/ចាស ឬ ទេ)", + "NOTES": "កំណត់សម្គាល់ / កាលបរិច្ឆេទដាំដំណាំអាយុវែង / និងព័ត៌មានផ្សេងៗ។", + "SEED_CROP_OR_PLANTING_STOCK": "ប្រភេទដំណាំគ្រាប់ពូជ / ពូជដំណាំ ឬសម្ភារៈដាំដុះ", + "STATUS_CERTIFIED_ORGANIC": "ស្ថានភាពគ្រាប់ពូជ/សម្ភារៈដាំ = បានទទួលវិញ្ញាបនបត្រសរីរាង្គ (បាទ/ចាស ឬ ទេ)", + "SUPPLIER": "ប្រភព/អ្នកផ្គត់ផ្គង់", + "TREATMENT_DOCS_AVAILABLE": "ឯកសារពាក់ព័ន្ធនឹងការព្យាបាល មានឬអត់? (បាទ/ចាស ឬ ទេ)" + }, + "TO": "ចំពោះ" + }, + "RECORD_I": { + "CLEANERS": "សារធាតុសម្អាត ឬ អ្នកសម្អាត", + "CROP_PRODUCTION_AIDS": "សម្ភារៈ/សារធាតុជួយការផលិតដំណាំ", + "EXPORT_DOCUMENT_NAME": "កំណត់ត្រា អាយ", + "HEADER": "កំណត់ត្រា អាយ", + "INPUT_CATEGORY": "ប្រភេទធាតុចូល ឬ ប្រភេទសម្ភារៈប្រើប្រាស់", + "LOCATIONS": "ទីតាំង", + "NOTE": { + "LIST_ALL": "រាយបញ្ជីធាតុចូលទាំងអស់ដែលបានប្រើក្នុងរយៈពេល 12 ខែចុងក្រោយ ឬចាប់តាំងពីបានដាក់បញ្ជូន កំណត់ត្រា I លើកចុងក្រោយ។ អ្នកអាចប្រើឯកសារនេះ ដើម្បីកត់ត្រាធាតុចូលជាបន្តបន្ទាប់ពេញរដូវកាលបាន។", + "LIVESTOCK_INPUTS": "ចំណាំ៖ ធាតុចូលសម្រាប់សត្វចិញ្ចឹម ដូចជា អាហារសត្វ បន្ថែមក្នុងអាហារ និងអាហារបំប៉ន ផលិតផលថែទាំសុខភាព និងសម្ភារៈជួយផលិតកម្ម ព្រមទាំងសម្ភារៈក្រាលដេកសត្វជាដើម ត្រូវកត់ត្រានៅក្នុង កំណត់ត្រា LI – ធាតុចូលសត្វចិញ្ចឹម។", + "ONE": { + "PART_1": "ការកែលម្អដី អាហារបំប៉នដំណាំ សម្ភារៈជួយផលិតកម្មដំណាំ និងសម្ភារៈផ្សេងៗ៖", + "PART_2": "ឧទាហរណ៍ ដូចជា សម្ភារៈគ្របដី ជី ថ្នាំបាញ់លើស្លឹក ជីកំប៉ុស លាមកសត្វ ល្បាយដីដាំកូនឈើ ឬសមាសធាតុនៃវា និងសារធាតុកែលម្អដីផ្សេងៗជាដើម។" + }, + "PLEASE_USE_SEPARATE_RECORD": "សូមប្រើកំណត់ត្រាធាតុចូលដោយឡែកសម្រាប់ប្រភេទធាតុចូលនីមួយៗ ដូចបានពន្យល់ខាងក្រោម ហើយបញ្ចូនឡើង មួយៗទៅកន្លែងបញ្ចូនដែលត្រូវគ្នានៅក្នុងផ្នែក 99 -​​ ហើយបញ្ចូនឡើង៖", + "PREP_INPUTS": "ចំណាំ៖ ធាតុចូលសម្រាប់ការរៀបចំ/កែច្នៃ ដូចជា សារធាតុបន្ថែមអាហារ គ្រឿងផ្សំផ្សេងៗ និងសារធាតុជួយដំណើរការផលិត ត្រូវកត់ត្រានៅក្នុង កំណត់ត្រា PM – បញ្ជីគ្រឿងផ្សំមេ និងសារធាតុជួយដំណើរការផលិត។", + "TWO": "សារធាតុសម្អាត ថ្នាំសម្លាប់មេរោគ សារធាតុសម្លាប់/បន្សាបមេរោគ និងសារធាតុគ្រប់គ្រងសត្វល្អិតក្នុងអគារ/ទីតាំងផលិតកម្ម។" + }, + "REPORTING_PERIOD": "រយៈពេលរាយការណ៍", + "TABLE_COLUMN": { + "CROP_FIELD_APPLIED_TO": "ដំណាំ/វាលដីដែលបានប្រើ ឬអង្គភាពផលិតកម្មដែលបានអនុវត្ត", + "DATE_USED": "កាលបរិច្ឆេទដែលបានប្រើ​", + "LISTED_IN_PSL": "មានចុះបញ្ជីនៅក្នុង ភីអែសអិល ឬអត់? (បាទ/ចាស ឬ ទេ)", + "NOTES": "កំណត់ចំណាំ", + "PRODUCT_NAME": "ឈ្មោះផលិតផល", + "QUANTITY": "បរិមាណ", + "SUPPLIER": "ឈ្មោះម៉ាក ឬ ប្រភព/អ្នកផ្គត់ផ្គង់" + }, + "VARIETALS": "ប្រភេទពូជ" + }, + "Y": "បាទ/ចាស", + "YES": "បាទ/ចាស" +} diff --git a/packages/api/src/middleware/acl/hasFarmAccess.js b/packages/api/src/middleware/acl/hasFarmAccess.js index 5c38db570f..102daf5502 100644 --- a/packages/api/src/middleware/acl/hasFarmAccess.js +++ b/packages/api/src/middleware/acl/hasFarmAccess.js @@ -30,8 +30,7 @@ const entitiesGetters = { nomination_id: fromNomination, transplant_task: fromTransPlantTask, product_id: fromProductFarm, - tape_survey_id: fromTapeSurvey, - submission_id: fromTapeSurvey, + submission_id: fromSurveyResponse, }; import userFarmModel from '../../models/userFarmModel.js'; @@ -285,8 +284,8 @@ function fromProductFarm(product_id, _next, farm_id) { return knex('product_farm').where({ product_id, farm_id }).first(); } -function fromTapeSurvey(submission_id) { - return knex('tape_survey').where({ submission_id }).first(); +function fromSurveyResponse(submission_id) { + return knex('survey_response').where({ submission_id }).first(); } function sameFarm(object, farm) { diff --git a/packages/api/src/models/tapeSurveyModel.js b/packages/api/src/models/surveyResponseModel.js similarity index 83% rename from packages/api/src/models/tapeSurveyModel.js rename to packages/api/src/models/surveyResponseModel.js index 6ad803d798..5dfe595b87 100644 --- a/packages/api/src/models/tapeSurveyModel.js +++ b/packages/api/src/models/surveyResponseModel.js @@ -15,9 +15,9 @@ import BaseFormatModel from './baseFormatModel.js'; -class TapeSurveyModel extends BaseFormatModel { +class SurveyResponseModel extends BaseFormatModel { static get tableName() { - return 'tape_survey'; + return 'survey_response'; } static get idColumn() { @@ -27,14 +27,15 @@ class TapeSurveyModel extends BaseFormatModel { static get jsonSchema() { return { type: 'object', - required: ['farm_id', 'survey_version', 'project_id', 'survey_step', 'survey_response'], + required: ['farm_id', 'survey_key', 'survey_version', 'project_id', 'survey_response'], properties: { id: { type: 'integer' }, submission_id: { type: 'string' }, farm_id: { type: 'string' }, + survey_key: { type: 'string' }, survey_version: { type: 'string' }, project_id: { type: 'string' }, - survey_step: { type: 'string' }, + survey_step: { type: ['string', 'null'] }, survey_response: { type: 'object' }, created_by_user_id: { type: 'string' }, created_at: { type: 'string', format: 'date-time' }, @@ -54,4 +55,4 @@ class TapeSurveyModel extends BaseFormatModel { } } -export default TapeSurveyModel; +export default SurveyResponseModel; diff --git a/packages/api/src/routes/tapeSurveyRoute.js b/packages/api/src/routes/surveyResponseRoute.ts similarity index 64% rename from packages/api/src/routes/tapeSurveyRoute.js rename to packages/api/src/routes/surveyResponseRoute.ts index caa85db6a9..2bbd0967a5 100644 --- a/packages/api/src/routes/tapeSurveyRoute.js +++ b/packages/api/src/routes/surveyResponseRoute.ts @@ -16,24 +16,30 @@ import express from 'express'; import checkScope from '../middleware/acl/checkScope.js'; import hasFarmAccess from '../middleware/acl/hasFarmAccess.js'; -import tapeSurveyController from '../controllers/tapeSurveyController.js'; +import surveyResponseController from '../controllers/surveyResponseController.js'; const router = express.Router(); router.post( '/', - checkScope(['add:tape_survey']), + checkScope(['add:survey_response']), hasFarmAccess({ body: 'farm_id' }), - tapeSurveyController.createTapeSurvey(), + surveyResponseController.createSurveyResponse(), ); -router.get('/', checkScope(['get:tape_survey']), tapeSurveyController.getTapeSurvey()); +// Latest survey response of the kind given by the survey_key query param +router.get( + '/', + checkScope(['get:survey_response']), + surveyResponseController.getLatestSurveyResponse(), +); +// Non-destructive update: appends a new version sharing the submission_id router.patch( '/:submission_id', - checkScope(['edit:tape_survey']), + checkScope(['edit:survey_response']), hasFarmAccess({ params: 'submission_id' }), - tapeSurveyController.updateTapeSurvey(), + surveyResponseController.updateSurveyResponse(), ); export default router; diff --git a/packages/api/src/server.ts b/packages/api/src/server.ts index 6cfcde1864..a16744df03 100644 --- a/packages/api/src/server.ts +++ b/packages/api/src/server.ts @@ -31,7 +31,7 @@ if (process.env.SENTRY_DSN && environment !== 'development') { // Automatically instrument Node.js libraries and frameworks ...Sentry.autoDiscoverNodePerformanceMonitoringIntegrations(), ], - release: '3.12.0', + release: '3.12.1', // Set tracesSampleRate to 1.0 to capture 100% // of transactions for performance monitoring. // We recommend adjusting this value in production @@ -180,7 +180,7 @@ import marketDirectoryInfoRoute from './routes/marketDirectoryInfoRoute.js'; import marketProductCategoryRoute from './routes/marketProductCategoryRoute.js'; import marketDirectoryPartnerRoute from './routes/marketDirectoryPartnerRoute.js'; import offlineEventLogRoute from './routes/offlineEventLogRoute.js'; -import tapeSurveyRoute from './routes/tapeSurveyRoute.js'; +import surveyResponseRoute from './routes/surveyResponseRoute.js'; import farmNoteRoute from './routes/farmNoteRoute.js'; import farmNotesReadRoute from './routes/farmNotesReadRoute.js'; @@ -364,7 +364,7 @@ app .use('/market_product_categories', marketProductCategoryRoute) .use('/market_directory_partners', marketDirectoryPartnerRoute) .use('/offline_event_log', offlineEventLogRoute) - .use('/tape_survey', tapeSurveyRoute) + .use('/survey_response', surveyResponseRoute) .use('/farm_notes', farmNoteRoute) .use('/farm_notes_read', farmNotesReadRoute); diff --git a/packages/api/src/templates/locales/km.json b/packages/api/src/templates/locales/km.json new file mode 100644 index 0000000000..b736e67a1c --- /dev/null +++ b/packages/api/src/templates/locales/km.json @@ -0,0 +1,105 @@ +{ + "TEMPLATE": { + "DEAR": "ជាទីគោរព", + "CHEERS": "លាហើយ / អបអរសាទរ", + "LITEFARM_TEAM": "ក្រុមការងារឡៃហ្វាម", + "NO_RESPONSE": "សូមកុំឆ្លើយតបទៅអ៊ីមែលនេះ។", + "GET_IN_TOUCH": "ដើម្បីទាក់ទងមកយើង សូមចុច", + "HELP": "ជំនួយ", + "OR": "ឬ", + "CONTACT": "ទាក់ទងមកយើង" + }, + "HELP_REQUEST": { + "RESPONSE": "សូមអរគុណដែលបានទាក់ទងមកយើង។ សមាជិកក្រុមគាំទ្ររបស់យើងម្នាក់នឹងទាក់ទងទៅអ្នកក្នុងរយៈពេល 48 ម៉ោង។ សេចក្តីសង្ខេបនៃសំណើរបស់អ្នកត្រូវបានបង្ហាញខាងក្រោម។", + "TYPE_HEADER": "ប្រភេទនៃការគាំទ្រ", + "MESSAGE_HEADER": "សារ", + "REQUEST_INFORMATION": "ស្នើសុំព័ត៌មាន", + "REPORT_A_BUG": "រាយការណ៍អំពីកំហុសកម្មវិធី", + "REQUEST_A_FEATURE": "ស្នើសុំមុខងារថ្មី", + "OTHER": "ផ្សេងទៀត", + "CONTACT_METHOD_HEADER": "វិធីទំនាក់ទំនងដែលចូលចិត្ត", + "SUBJECT": "សំណើសុំជំនួយរបស់អ្នកពីឡៃហ្វាមនៅ", + "OOO_RESPONSE": "សូមអរគុណដែលបានទាក់ទងមកយើង។ សូមជ្រាបថា ក្រុមការងាររបស់យើងកំពុងមិននៅការិយាល័យរហូតដល់ {{oooEndDate}}។ យើងនឹងឆ្លើយតបសាររបស់អ្នកឲ្យបានឆាប់តាមដែលអាចធ្វើទៅបាន បន្ទាប់ពីយើងត្រឡប់មកវិញ។ សូមអរគុណចំពោះការយល់ដឹងរបស់អ្នក! សេចក្តីសង្ខេបនៃសំណើរបស់អ្នកត្រូវបានបង្ហាញខាងក្រោម។" + }, + "INVITE": { + "GREAT_FOLK": "ក្រុមការងារល្អៗនៅ", + "INVITED_YOU": "បានអញ្ជើញអ្នកឲ្យចូលរួមជាក្រុមរបស់ពួកគេនៅ ឡៃហ្វាម! ឡៃហ្វាម គឺជាកម្មវិធីសូហ្វវែរ អាចប្រើ និងអភិវឌ្ឍបានដោយសេរីមួយដែលជួយកសិករគ្រប់គ្រងកសិដ្ឋានរបស់ពួកគេ។ អ្នកអាចអានបន្ថែមអំពី ឡៃហ្វាម នៅ", + "YOU_CAN_ACCEPT": "អ្នកអាចទទួលយកការអញ្ជើញនេះ (លើឧបករណ៍ណាមួយក៏បាន) ដោយប្រើប៊ូតុងខាងក្រោម", + "SUBJECT0": "អ្នកត្រូវបានអញ្ជើញឲ្យចូលរួម", + "SUBJECT1": "នៅលើ ឡៃហ្វាម!" + }, + "PASSWORD_RESET_REQUEST": { + "DID_YOU_FORGET": "តើអ្នកភ្លេចពាក្យសម្ងាត់ ឡៃហ្វាម របស់អ្នកមែនទេ? មិនជាបញ្ហាទេ! សូមចុចប៊ូតុង ‘កំណត់ឡើងវិញ’ ខាងក្រោម ហើយការចូលប្រើរបស់អ្នកនឹងត្រូវបានស្តារឡើងវិញក្នុងពេលឆាប់ៗនេះ។", + "RESET": "កំណត់ពាក្យសម្ងាត់ថ្មី", + "IGNORE": "បើអ្នកមិនបានស្នើឲ្យយើងផ្ញើអ៊ីមែលនេះទេ អ្នកអាចមិនចាំបាច់យកចិត្តទុកដាក់បាន។ មិនមានការផ្លាស់ប្ដូរណាមួយបានធ្វើលើគណនីរបស់អ្នកទេ។", + "SUBJECT": "សំណើរកំណត់ពាក្យសម្ងាត់ថ្មី" + }, + "PASSWORD_RESET_CONFIRMATION": { + "UPDATED": "យើងបានធ្វើបច្ចុប្បន្នភាពពាក្យសម្ងាត់ ឡែហ្វាម របស់អ្នកហើយ។ សូមចុច ‘ចូលទៅ’ ខាងក្រោម ដើម្បីចូលប្រើគណនីរបស់អ្នក។", + "SUBJECT": "ពាក្យសម្ងាត់ ឡៃហ្វាម របស់អ្នកត្រូវបានផ្លាស់ប្តូរហើយ" + }, + "RESTORE_ACCESS": { + "ADMIN": "មើលទៅដូចជា អ្នកគ្រប់គ្រងម្នាក់នៅ", + "RESTORED": "បានបន្តសិទ្ធិឲ្យអ្នកចូលប្រើកសិដ្ឋានរបស់ពួកគេនៅលើ ឡៃហ្វាម វិញហើយ។ សូមស្វាគមន៍ត្រឡប់មកវិញ!", + "CLICK_BELOW": "អ្នកអាចចូលគណនីវិញបានដោយចុចខាងក្រោម", + "SUBJECT0": "សិទ្ធិចូលប្រើរបស់អ្នកទៅកាន់", + "SUBJECT1": "ត្រូវបានស្តារឡើងវិញហើយ!" + }, + "REVOKE_ACCESS": { + "ADMIN": "មើលទៅដូចជា អ្នកគ្រប់គ្រងម្នាក់នៅ", + "REVOKE": "បានដកសិទ្ធិចូលប្រើរបស់អ្នកទៅកាន់កសិដ្ឋានរបស់ពួកគេនៅលើ ឡៃហ្វាម ហើយ។ ប្រសិនបើនេះធ្វើឲ្យអ្នកភ្ញាក់ផ្អើល អ្នកគួរទាក់ទងអ្នកដែលអ្នកស្គាល់នៅទីនោះ ដើម្បីដោះស្រាយបញ្ហានេះ។", + "SUBJECT0": "អ្នកបានបាត់បង់សិទ្ធិចូលប្រើទៅកាន់", + "SUBJECT1": "នៅលើ ឡៃហ្វាម!" + }, + "ACCEPT_INVITE_CONFIRMATION": { + "CONGRATS": "សូមអបអរសាទរដែលអ្នកបានក្លាយជាសមាជិកថ្មីបំផុត", + "AT": "នៅ", + "CLICK_BELOW": "អ្នកអាចចូលគណនី (លើឧបករណ៍ណាមួយក៏បាន) ដោយប្រើប៊ូតុងខាងក្រោម", + "SUBJECT": "អ្នកបានចូលរួមដោយជោគជ័យហើយ" + }, + "CREATE_ACCOUNT_CONFIRMATION": { + "WELCOME": "សូមស្វាគមន៍មកកាន់ ឡៃហ្វាម! ឡៃហ្វាម គឺជាកម្មវិធីសូហ្វវែរកុំព្យូទ័រប្រភពបើកចំហ មួយដែលជួយកសិករគ្រប់គ្រងកសិដ្ឋានរបស់ពួកគេ។ អ្នកអាចអានព័ត៌មានបន្ថែមអំពី ឡៃហ្វាម នៅ", + "CLICK_BELOW": "អ្នកក៏អាចចូលគណនី (លើឧបករណ៍ណាមួយក៏បាន) ដោយប្រើប៊ូតុងខាងក្រោមដែរ", + "SUBJECT": "សូមស្វាគមន៍មកកាន់​ឡៃហ្វាម!" + }, + "WITHHOLD_CONSENT": { + "RECENT": "ថ្មីៗនេះ ខណៈពេលកំពុងចូលរួម", + "WITHHOLD": "នៅក្នុងកម្មវិធី ឡៃហ្វាម អ្នកបានសម្រេចចិត្តមិនផ្តល់ការយល់ព្រម ចំពោះគោលការណ៍ឯកជនភាពរបស់ ឡៃហ្វាម។ នេះគឺជាសិទ្ធិរបស់អ្នកពិតប្រាកដ ប៉ុន្តែវាមានន័យថា អ្នកនឹងមិនអាចចូលប្រើកម្មវិធីនេះបានទេ។ យើងសូមអភ័យទោសចំពោះរឿងនេះ។", + "DEACTIVATE": "យើងបានបិទការភ្ជាប់របស់អ្នកទៅកាន់", + "HOWEVER": "ទោះយ៉ាងណា យើងនៅតែមានព័ត៌មានមូលដ្ឋានដែលអ្នកបានផ្តល់ឲ្យពេលបង្កើតគណនីអ្នកប្រើប្រាស់។ ប្រសិនបើអ្នកមានការភ្ជាប់ជាមួយកសិដ្ឋានផ្សេងៗ យើងក៏នៅតែមានព័ត៌មានណាដែលអ្នកបានបញ្ចូលពេលធ្វើការជាមួយកសិដ្ឋានទាំងនោះផងដែរ។", + "RIGHT": "អ្នកមានសិទ្ធិដូចខាងក្រោមទាក់ទងនឹងទិន្នន័យរបស់អ្នក", + "COPY": "ដើម្បីដឹងថាយើងមានទិន្នន័យអ្វីខ្លះអំពីអ្នក និងស្នើសុំច្បាប់ចម្លងនៃទិន្នន័យនោះ", + "UPDATE": "ដើម្បីធ្វើបច្ចុប្បន្នភាព ឬកែតម្រូវទិន្នន័យណាមួយដែលយើងមានអំពីអ្នក", + "STOP": "ស្នើឲ្យយើងឈប់ប្រមូលទិន្នន័យរបស់អ្នក (អ្នកទើបបានធ្វើសកម្មភាពនេះរួចហើយ)", + "TRANSFER": "ស្នើសុំផ្ទេរទិន្នន័យរបស់អ្នក", + "DELETE": "ស្នើសុំឲ្យយើងលុបទិន្នន័យរបស់អ្នក", + "TO_REQUEST": "ដើម្បីស្នើសុំសកម្មភាពណាមួយទាំងនេះ សូមផ្ញើអ៊ីមែលទៅកាន់", + "SUPPORT": "ជាមួយនឹងសំណើរបស់អ្នក ហើយយើងនឹងពិនិត្យ និងដោះស្រាយឲ្យអ្នក។", + "OTHERWISE": "បើមិនដូច្នោះទេ ប្រសិនបើអ្នកផ្លាស់ប្តូរចិត្ត អ្នកអាចចូលគណនីវិញ (លើឧបករណ៍ណាមួយក៏បាន) នៅពេលណាក៏បាន ហើយទទួលយកគោលការណ៍ឯកជនភាពរបស់យើង ដោយប្រើប៊ូតុងខាងក្រោម", + "RESTORE": "បើអ្នកធ្វើដូច្នោះ អ្នកនឹងអាចចូលប្រើប្រព័ន្ធ ឡៃហ្វាមវិញម្តងទៀតបាន។", + "SUBJECT": "អ្នកមិនបានយល់ព្រមជាមួយគោលការណ៍ឯកជនភាពរបស់ ឡៃហ្វាម ទេ — នេះគឺជាជម្រើសរបស់អ្នក" + }, + "EXPORT_MAP": { + "EXPORT": "នេះគឺជាផែនទីកសិដ្ឋានសម្រាប់នាំចេញទៅ", + "REQUESTED": "ដែលអ្នកបានស្នើសុំលើ​ ឡៃហ្វាម។", + "GREETING": "សូមឲ្យអ្នកមានថ្ងៃល្អ!", + "SUBJECT0": "នេះគឺជាផែនទីកសិដ្ឋានរបស់អ្នកសំរាប់", + "SUBJECT1": "នៅលើ​ឡៃហ្វាម" + }, + "EXPORT": { + "SEASON": "យើងសង្ឃឹមថា អ្នកមានរដូវកាលដ៏អស្ចារ្យនៅ", + "CERTIFICATION": " អ្នកអាចចុចលើតំណភ្ជាប់ខាងក្រោម ដើម្បីទាញយកឯកសារបង្រួម ដែលមានឯកសារបញ្ជាក់វិញ្ញាបនបត្រ និងឯកសារគាំទ្រទាំងអស់ (រូបថតកញ្ចប់គ្រាប់ពូជ ស្កេនបង្កាន់ដៃធាតុចូល ។ល។) សម្រាប់រយៈពេលរាយការណ៍របស់អ្នក។", + "PRIVACY": "នៅ ឡៃហ្វាម យើងយកចិត្តទុកដាក់ខ្លាំងចំពោះភាពឯកជនរបស់អ្នក ដូច្នេះអ្នកត្រូវចូលគណនីសិន មុននឹងអាចចូលមើលឯកសារដែលបាននាំចេញរបស់អ្នក។ សូមអភ័យទោសចំពោះភាពមិនស្រួលណាមួយ។ សូមជូនពរឲ្យការដាក់ស្នើរបស់អ្នកទទួលបានជោគជ័យ និងអរគុណដែលបានប្រើ ឡៃហ្វាម!", + "SUBJECT": "ឯកសារបញ្ជាក់ដែលបាននាំចេញរបស់អ្នកពី ឡៃហ្វាម", + "HI": "សួស្តី", + "GET_YOUR_EXPORT": "ទទួលឯកសារ" + }, + "COMMON": { + "JOIN": "ចូលរួម", + "LOG_IN": "ចូលគណនី", + "OWNER": "ម្ចាស់", + "MANAGER": "អ្នកគ្រប់គ្រង", + "WORKER": "កម្មករ", + "EXTENSION_OFFICER": "មន្រ្តីផ្សព្វផ្សាយ" + } +} diff --git a/packages/api/src/util/ensembleService.ts b/packages/api/src/util/ensembleService.ts index 90816f2239..d82c6f0a5e 100644 --- a/packages/api/src/util/ensembleService.ts +++ b/packages/api/src/util/ensembleService.ts @@ -138,13 +138,16 @@ export const getIrrigationPrescriptions = async ( // Get and check data const irrigationPrescriptionListResponse = await ensembleAPICall(axiosObject, onError); + // Ensemble paginates this endpoint, returning prescriptions under 'results' + const { results: prescriptions = [] } = irrigationPrescriptionListResponse.data ?? {}; + // Add url names (org and system) to each prescription const organisation = await getValidEnsembleOrg(externalOrganizationIds.org_uuid); const systemUrlNames = Object.fromEntries( (organisation?.systems ?? []).map((system) => [system.pk, system.url_name]), ); - irrigationPrescriptionListResponse.data = irrigationPrescriptionListResponse.data.map( + irrigationPrescriptionListResponse.data = prescriptions.map( (prescription: ExternalIrrigationPrescription) => ({ ...prescription, organisation_url_name: organisation?.url_name, diff --git a/packages/api/tests/irrigation_prescription.test.ts b/packages/api/tests/irrigation_prescription.test.ts index 124d965ba2..cc5ba9de4c 100644 --- a/packages/api/tests/irrigation_prescription.test.ts +++ b/packages/api/tests/irrigation_prescription.test.ts @@ -158,9 +158,14 @@ describe('Get Irrigation Prescription Tests', () => { const startDate = today.toISOString().split('T')[0]; const endDate = addDaysToDate(today, 1).toISOString().split('T')[0]; - // GET prescription list + // GET prescription list — paginated envelope mockedAxios.mockResolvedValueOnce({ - data: externalIrrigationPrescriptions, + data: { + count: externalIrrigationPrescriptions.length, + next: null, + previous: null, + results: externalIrrigationPrescriptions, + }, }); // GET Ensemble Organisation (org content not part of tests) @@ -193,9 +198,14 @@ describe('Get Irrigation Prescription Tests', () => { expect(irrigationPrescriptionsWithTasks.length).toBe(2); expect(irrigationPrescriptionsWithTasks[0].task_id).toBeTruthy(); - // GET prescription list + // GET prescription list — paginated envelope mockedAxios.mockResolvedValueOnce({ - data: irrigationPrescriptionsWithTasks, + data: { + count: irrigationPrescriptionsWithTasks.length, + next: null, + previous: null, + results: irrigationPrescriptionsWithTasks, + }, }); // GET Ensemble Organisation (org content not part of tests) diff --git a/packages/api/tests/surveyResponse.test.js b/packages/api/tests/surveyResponse.test.js new file mode 100644 index 0000000000..3500699d2a --- /dev/null +++ b/packages/api/tests/surveyResponse.test.js @@ -0,0 +1,275 @@ +/* + * Copyright 2026 LiteFarm.org + * This file is part of LiteFarm. + * + * LiteFarm is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * LiteFarm is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details, see . + */ + +import chai from 'chai'; +import chaiHttp from 'chai-http'; +chai.use(chaiHttp); +import server from './../src/server.js'; +import knex from '../src/util/knex.js'; +import { tableCleanup } from './testEnvironment.js'; + +jest.mock('jsdom'); +jest.mock('../src/middleware/acl/checkJwt.js', () => + jest.fn((req, _res, next) => { + req.auth = {}; + req.auth.user_id = req.get('user_id'); + next(); + }), +); + +import mocks from './mock.factories.js'; +import { createUserFarmIds } from './utils/testDataSetup.js'; + +describe('Survey response endpoint tests', () => { + let owner; + let farm; + let _ownerFarm; + + function fakeUserFarm(role = 1) { + return { ...mocks.fakeUserFarm(), role_id: role }; + } + + async function postRequest(data, { user_id = owner.user_id, farm_id = farm.farm_id } = {}) { + return chai + .request(server) + .post('/survey_response') + .set('Content-Type', 'application/json') + .set('user_id', user_id) + .set('farm_id', farm_id) + .send(data); + } + + async function getRequest({ + user_id = owner.user_id, + farm_id = farm.farm_id, + survey_key = 'tape', + } = {}) { + return chai + .request(server) + .get('/survey_response') + .query({ survey_key }) + .set('user_id', user_id) + .set('farm_id', farm_id); + } + + async function patchRequest( + submission_id, + survey_response, + { user_id = owner.user_id, farm_id = farm.farm_id } = {}, + ) { + return chai + .request(server) + .patch(`/survey_response/${submission_id}`) + .set('Content-Type', 'application/json') + .set('user_id', user_id) + .set('farm_id', farm_id) + .send({ survey_response }); + } + + function fakeSurveyPayload(farm_id, survey_key = 'tape') { + return { + farm_id, + survey_key, + survey_response: { + survey_version: 'v1', + project_id: 'project-1', + survey_step: 'step-1', + }, + }; + } + + beforeEach(async () => { + [owner] = await mocks.usersFactory(); + [farm] = await mocks.farmFactory(); + [_ownerFarm] = await mocks.userFarmFactory( + { promisedUser: [owner], promisedFarm: [farm] }, + fakeUserFarm(1), + ); + }); + + afterEach(async () => { + await tableCleanup(knex); + }); + + afterAll(async () => { + await knex.destroy(); + }); + + describe('POST /survey_response', () => { + test('Admin roles should be able to create a survey response', async () => { + const adminRoles = [1, 2, 5]; + for (const role of adminRoles) { + const userFarmIds = await createUserFarmIds(role); + const res = await postRequest(fakeSurveyPayload(userFarmIds.farm_id), userFarmIds); + + expect(res.status).toBe(201); + const getRes = await getRequest(userFarmIds); + expect(getRes.status).toBe(200); + expect(getRes.body?.survey_response?.survey_step).toBe('step-1'); + } + }); + + test('Worker should not be able to create a survey response', async () => { + const userFarmIds = await createUserFarmIds(3); + const res = await postRequest(fakeSurveyPayload(userFarmIds.farm_id), userFarmIds); + expect(res.status).toBe(403); + }); + + test('Should return 403 if user is not part of the farm', async () => { + const idsA = await createUserFarmIds(1); + const idsB = await createUserFarmIds(1); + const res = await postRequest(fakeSurveyPayload(idsA.farm_id), { + farm_id: idsA.farm_id, + user_id: idsB.user_id, + }); + expect(res.status).toBe(403); + }); + + test('Should return 400 when survey_key is missing', async () => { + const { survey_key: _omitted, ...payloadWithoutKey } = fakeSurveyPayload(farm.farm_id); + const res = await postRequest(payloadWithoutKey); + expect(res.status).toBe(400); + }); + }); + + describe('GET /survey_response', () => { + test('Should return 200 with no survey response when none exist', async () => { + const res = await getRequest(); + expect(res.status).toBe(200); + expect(res.body?.survey_response).toBeUndefined(); + }); + + test('Should return the most recent survey response of the requested kind', async () => { + await postRequest(fakeSurveyPayload(farm.farm_id)); + await postRequest({ + ...fakeSurveyPayload(farm.farm_id), + survey_response: { + survey_version: 'v2', + project_id: 'project-2', + survey_step: 'step-2', + }, + }); + + const res = await getRequest(); + expect(res.status).toBe(200); + expect(res.body?.survey_response?.survey_step).toBe('step-2'); + }); + + test('Should not return another survey kind for the farm', async () => { + await postRequest(fakeSurveyPayload(farm.farm_id, 'tape')); + const res = await getRequest({ survey_key: 'some_other_survey' }); + expect(res.status).toBe(200); + expect(res.body?.survey_response).toBeUndefined(); + }); + + test('Should return 400 when survey_key is missing', async () => { + const res = await chai + .request(server) + .get('/survey_response') + .set('user_id', owner.user_id) + .set('farm_id', farm.farm_id); + expect(res.status).toBe(400); + }); + + test('Worker should not be able to get a survey response', async () => { + const userFarmIds = await createUserFarmIds(3); + const res = await getRequest(userFarmIds); + expect(res.status).toBe(403); + }); + + test('Should return 403 if user is not part of the farm', async () => { + const idsA = await createUserFarmIds(1); + const idsB = await createUserFarmIds(1); + const res = await getRequest({ farm_id: idsA.farm_id, user_id: idsB.user_id }); + expect(res.status).toBe(403); + }); + }); + + describe('PATCH /survey_response/:submission_id', () => { + // Creates a survey response, then returns the submission_id the API assigned it. + async function createSubmission(farm_id = farm.farm_id, survey_key = 'tape') { + await postRequest(fakeSurveyPayload(farm_id, survey_key), { farm_id }); + const getRes = await getRequest({ farm_id, survey_key }); + return getRes.body.submission_id; + } + + test('Update appends a new version and leaves the earlier one in place', async () => { + const submission_id = await createSubmission(); + + const res = await patchRequest(submission_id, { + survey_version: 'v2', + project_id: 'project-2', + survey_step: 'step-2', + }); + expect(res.status).toBe(204); + + // getLatestSurveyResponse returns the new version. + const getRes = await getRequest(); + expect(getRes.status).toBe(200); + expect(getRes.body?.survey_response?.survey_step).toBe('step-2'); + + // Both versions are retained under the one submission_id; nothing was overwritten. + const rows = await knex('survey_response').where({ submission_id }).orderBy('id'); + expect(rows.length).toBe(2); + expect(rows[0].survey_response.survey_step).toBe('step-1'); + expect(rows[1].survey_response.survey_step).toBe('step-2'); + }); + + test('Update reuses the existing survey_key rather than the request body', async () => { + const submission_id = await createSubmission(farm.farm_id, 'tape'); + + await patchRequest(submission_id, { + survey_version: 'v2', + project_id: 'project-2', + survey_step: 'step-2', + }); + + const rows = await knex('survey_response').where({ submission_id }); + expect(rows.every((row) => row.survey_key === 'tape')).toBe(true); + }); + + test('Should return 403 for an unknown submission_id', async () => { + // hasFarmAccess finds no row for the submission_id and rejects before the controller runs + const res = await patchRequest('00000000-0000-0000-0000-000000000000', { + survey_version: 'v2', + project_id: 'project-2', + survey_step: 'step-2', + }); + expect(res.status).toBe(403); + }); + + test('Worker should not be able to update a survey response', async () => { + const submission_id = await createSubmission(); + const worker = await createUserFarmIds(3); + const res = await patchRequest( + submission_id, + { survey_version: 'v2', project_id: 'project-2', survey_step: 'step-2' }, + worker, + ); + expect(res.status).toBe(403); + }); + + test('Should return 403 when the submission belongs to another farm', async () => { + const submission_id = await createSubmission(); + const otherOwner = await createUserFarmIds(1); + const res = await patchRequest( + submission_id, + { survey_version: 'v2', project_id: 'project-2', survey_step: 'step-2' }, + otherOwner, + ); + expect(res.status).toBe(403); + }); + }); +}); diff --git a/packages/api/tests/tapeSurvey.test.js b/packages/api/tests/tapeSurvey.test.js deleted file mode 100644 index c52c89f285..0000000000 --- a/packages/api/tests/tapeSurvey.test.js +++ /dev/null @@ -1,223 +0,0 @@ -/* - * Copyright (C) 2026 Free Software Foundation, Inc. - * This file (tapeSurvey.test.js) is part of LiteFarm. - * - * LiteFarm is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * LiteFarm is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details, see . - */ - -import chai from 'chai'; -import chaiHttp from 'chai-http'; -chai.use(chaiHttp); -import server from './../src/server.js'; -import knex from '../src/util/knex.js'; -import { tableCleanup } from './testEnvironment.js'; - -jest.mock('jsdom'); -jest.mock('../src/middleware/acl/checkJwt.js', () => - jest.fn((req, _res, next) => { - req.auth = {}; - req.auth.user_id = req.get('user_id'); - next(); - }), -); - -import mocks from './mock.factories.js'; -import { createUserFarmIds } from './utils/testDataSetup.js'; - -describe('TapeSurvey endpoint tests', () => { - let owner; - let farm; - let _ownerFarm; - - function fakeUserFarm(role = 1) { - return { ...mocks.fakeUserFarm(), role_id: role }; - } - - async function postRequest(data, { user_id = owner.user_id, farm_id = farm.farm_id } = {}) { - return chai - .request(server) - .post('/tape_survey') - .set('Content-Type', 'application/json') - .set('user_id', user_id) - .set('farm_id', farm_id) - .send(data); - } - - async function getRequest({ user_id = owner.user_id, farm_id = farm.farm_id } = {}) { - return chai.request(server).get('/tape_survey').set('user_id', user_id).set('farm_id', farm_id); - } - - async function patchRequest( - submission_id, - data, - { user_id = owner.user_id, farm_id = farm.farm_id } = {}, - ) { - return chai - .request(server) - .patch(`/tape_survey/${submission_id}`) - .set('user_id', user_id) - .set('farm_id', farm_id) - .send(data); - } - - function fakeTapeSurveyPayload(farm_id) { - return { - farm_id, - survey_response: { - survey_version: 'v1', - project_id: 'project-1', - survey_step: 'step-1', - }, - }; - } - - beforeEach(async () => { - [owner] = await mocks.usersFactory(); - [farm] = await mocks.farmFactory(); - [_ownerFarm] = await mocks.userFarmFactory( - { promisedUser: [owner], promisedFarm: [farm] }, - fakeUserFarm(1), - ); - }); - - afterEach(async () => { - await tableCleanup(knex); - }); - - afterAll(async () => { - await knex.destroy(); - }); - - describe('POST /tape_survey', () => { - test('Admin roles should be able to create a tape survey', async () => { - const adminRoles = [1, 2, 5]; - for (const role of adminRoles) { - const userFarmIds = await createUserFarmIds(role); - const res = await postRequest(fakeTapeSurveyPayload(userFarmIds.farm_id), userFarmIds); - - expect(res.status).toBe(201); - const getRes = await getRequest(userFarmIds); - expect(getRes.status).toBe(200); - expect(getRes.body?.survey_response?.survey_step).toBe('step-1'); - } - }); - - test('Worker should not be able to create a tape survey', async () => { - const userFarmIds = await createUserFarmIds(3); - const res = await postRequest(fakeTapeSurveyPayload(userFarmIds.farm_id), userFarmIds); - expect(res.status).toBe(403); - }); - - test('Should return 403 if user is not part of the farm', async () => { - const idsA = await createUserFarmIds(1); - const idsB = await createUserFarmIds(1); - const res = await postRequest(fakeTapeSurveyPayload(idsA.farm_id), { - farm_id: idsA.farm_id, - user_id: idsB.user_id, - }); - expect(res.status).toBe(403); - }); - }); - - describe('GET /tape_survey', () => { - test('Should return 404 when none exist', async () => { - const res = await getRequest(); - expect(res.status).toBe(404); - expect(res.body.error).toBe('Tape survey not found'); - }); - - test('Should return the most recent tape survey', async () => { - await postRequest(fakeTapeSurveyPayload(farm.farm_id)); - await postRequest({ - ...fakeTapeSurveyPayload(farm.farm_id), - survey_response: { - survey_version: 'v2', - project_id: 'project-2', - survey_step: 'step-2', - }, - }); - - const res = await getRequest(); - expect(res.status).toBe(200); - expect(res.body?.survey_response?.survey_step).toBe('step-2'); - }); - - test('Worker should not be able to get tape survey', async () => { - const userFarmIds = await createUserFarmIds(3); - const res = await getRequest(userFarmIds); - expect(res.status).toBe(403); - }); - - test('Should return 403 if user is not part of the farm', async () => { - const idsA = await createUserFarmIds(1); - const idsB = await createUserFarmIds(1); - const res = await getRequest({ farm_id: idsA.farm_id, user_id: idsB.user_id }); - expect(res.status).toBe(403); - }); - }); - - describe('PATCH /tape_survey/:submission_id', () => { - test('Should insert a new record with same submission_id', async () => { - await postRequest(fakeTapeSurveyPayload(farm.farm_id)); - - const created = await getRequest(); - const submission_id = created.body.submission_id; - - const patchRes = await patchRequest(submission_id, { - farm_id: farm.farm_id, - survey_response: { - survey_version: 'v3', - project_id: 'project-3', - survey_step: 'step-3', - }, - }); - expect(patchRes.status).toBe(204); - - const latest = await getRequest(); - expect(latest.status).toBe(200); - expect(latest.body?.survey_response?.survey_step).toBe('step-3'); - expect(latest.body?.submission_id).toBe(submission_id); - }); - - test('Worker should not be able to patch a tape survey', async () => { - const userFarmIds = await createUserFarmIds(3); - await postRequest(fakeTapeSurveyPayload(userFarmIds.farm_id), userFarmIds); - const created = await getRequest(userFarmIds); - const submission_id = created.body.submission_id; - - const res = await patchRequest( - submission_id, - { - survey_response: { survey_version: 'v3', project_id: 'project-3', survey_step: 'step-3' }, - }, - userFarmIds, - ); - expect(res.status).toBe(403); - }); - - test('Should return 403 if user is not part of the farm', async () => { - const idsA = await createUserFarmIds(1); - const idsB = await createUserFarmIds(1); - await postRequest(fakeTapeSurveyPayload(idsA.farm_id), idsA); - const created = await getRequest(idsA); - const submission_id = created.body.submission_id; - - const res = await patchRequest( - submission_id, - { - survey_response: { survey_version: 'v3', project_id: 'project-3', survey_step: 'step-3' }, - }, - { farm_id: idsA.farm_id, user_id: idsB.user_id }, - ); - expect(res.status).toBe(403); - }); - }); -}); diff --git a/packages/api/tests/testEnvironment.js b/packages/api/tests/testEnvironment.js index 1046cdaca6..c8365d94f9 100644 --- a/packages/api/tests/testEnvironment.js +++ b/packages/api/tests/testEnvironment.js @@ -156,7 +156,7 @@ async function tableCleanup(knex) { DELETE FROM "market_directory_partner_country"; DELETE FROM "market_directory_partner_auth"; DELETE FROM "market_directory_partner"; - DELETE FROM "tape_survey"; + DELETE FROM "survey_response"; DELETE FROM "farm_notes_read"; DELETE FROM "farm_note"; DELETE FROM "location"; diff --git a/packages/api/tests/timeNotification.test.js b/packages/api/tests/timeNotification.test.js index 7b5963d040..3e1bcf3083 100644 --- a/packages/api/tests/timeNotification.test.js +++ b/packages/api/tests/timeNotification.test.js @@ -564,31 +564,44 @@ describe('Time Based Notification Tests', () => { }); test('One notification record should be created for the latest irrigation prescription on each location', async () => { - await mockedAxios.mockResolvedValue({ + const listResponse = { status: 201, - data: [ - { - id: 122, - recommended_start_date: '2025-05-07', - location_id: field.location_id, - }, - { - id: 123, - recommended_start_date: '2025-05-07', - location_id: secondField.location_id, - }, - { - id: 124, - recommended_start_date: '2025-05-08', - location_id: field.location_id, - }, - { - id: 125, - recommended_start_date: '2025-05-08', - location_id: secondField.location_id, - }, - ], - }); + data: { + count: 4, + next: null, + previous: null, + results: [ + { + id: 122, + recommended_start_date: '2025-05-07', + location_id: field.location_id, + }, + { + id: 123, + recommended_start_date: '2025-05-07', + location_id: secondField.location_id, + }, + { + id: 124, + recommended_start_date: '2025-05-08', + location_id: field.location_id, + }, + { + id: 125, + recommended_start_date: '2025-05-08', + location_id: secondField.location_id, + }, + ], + }, + }; + + // Prescription requests return the paginated envelope; the organisation + // lookup (and anything else) returns an empty array. + mockedAxios.mockImplementation((config) => + config.url?.includes('/prescriptions') + ? Promise.resolve(listResponse) + : Promise.resolve({ data: [] }), + ); const res = await postDailyNewIrrigationPrescriptions({ farm_id: farm.farm_id }); @@ -616,22 +629,80 @@ describe('Time Based Notification Tests', () => { ); }); + test('Selects the latest prescription per location when responses are in descending order', async () => { + // Prescription list in descending order. + const listResponse = { + status: 201, + data: { + count: 2, + next: null, + previous: null, + results: [ + { + id: 402, + recommended_start_date: '2025-05-08', + location_id: field.location_id, + }, + { + id: 401, + recommended_start_date: '2025-05-07', + location_id: field.location_id, + }, + ], + }, + }; + + // Prescription requests return the paginated envelope; the organisation + // lookup (and anything else) returns an empty array. + mockedAxios.mockImplementation((config) => + config.url?.includes('/prescriptions') + ? Promise.resolve(listResponse) + : Promise.resolve({ data: [] }), + ); + + const res = await postDailyNewIrrigationPrescriptions({ farm_id: farm.farm_id }); + + expect(res.status).toBe(201); + + const rows = await knex('notification') + .where('farm_id', farm.farm_id) + .whereRaw("(context->'irrigation_prescription_id') IN (?, ?)", [401, 402]); + + expect(rows).toHaveLength(1); + expect(rows[0].context.irrigation_prescription_id).toBe(402); + expect(rows[0].ref.url).toBe('/irrigation_prescription/402'); + }); + test('Repeat notifications are not sent for the same irrigation prescription', async () => { - await mockedAxios.mockResolvedValue({ + const listResponse = { status: 201, - data: [ - { - id: 223, - recommended_start_date: '2025-05-07', - location_id: field.location_id, - }, - { - id: 224, - recommended_start_date: '2025-05-08', - location_id: field.location_id, - }, - ], - }); + data: { + count: 2, + next: null, + previous: null, + results: [ + { + id: 223, + recommended_start_date: '2025-05-07', + location_id: field.location_id, + }, + { + id: 224, + recommended_start_date: '2025-05-08', + location_id: field.location_id, + }, + ], + }, + }; + + // Prescription requests return the paginated envelope; the organisation + // lookup (and anything else) returns an empty array + mockedAxios.mockImplementation((config) => + config.url?.includes('/prescriptions') + ? Promise.resolve(listResponse) + : Promise.resolve({ data: [] }), + ); + const res1 = await postDailyNewIrrigationPrescriptions({ farm_id: farm.farm_id }); // 201 is controller response for notifications sent @@ -651,31 +722,44 @@ describe('Time Based Notification Tests', () => { }); test('Notifications should not be sent for irrigation prescriptions associated with deleted locations', async () => { - await mockedAxios.mockResolvedValue({ + const listResponse = { status: 201, - data: [ - { - id: 301, - recommended_start_date: '2025-05-07', - location_id: field.location_id, - }, - { - id: 302, - recommended_start_date: '2025-05-07', - location_id: secondField.location_id, - }, - { - id: 303, - recommended_start_date: '2025-05-08', - location_id: field.location_id, - }, - { - id: 304, - recommended_start_date: '2025-05-08', - location_id: secondField.location_id, - }, - ], - }); + data: { + count: 4, + next: null, + previous: null, + results: [ + { + id: 301, + recommended_start_date: '2025-05-07', + location_id: field.location_id, + }, + { + id: 302, + recommended_start_date: '2025-05-07', + location_id: secondField.location_id, + }, + { + id: 303, + recommended_start_date: '2025-05-08', + location_id: field.location_id, + }, + { + id: 304, + recommended_start_date: '2025-05-08', + location_id: secondField.location_id, + }, + ], + }, + }; + + // Prescription requests return the paginated envelope; the organisation + // lookup (and anything else) returns an empty array. + mockedAxios.mockImplementation((config) => + config.url?.includes('/prescriptions') + ? Promise.resolve(listResponse) + : Promise.resolve({ data: [] }), + ); // Delete the first location await knex('location').where({ location_id: field.location_id }).update({ deleted: true }); diff --git a/packages/api/tsconfig.json b/packages/api/tsconfig.json index b157a0a14b..169fe36c56 100644 --- a/packages/api/tsconfig.json +++ b/packages/api/tsconfig.json @@ -4,7 +4,8 @@ "allowJs": true, "noEmit": true, "skipLibCheck": true, - "sourceMap": true + "sourceMap": true, + "types": ["node", "jest"] }, "include": ["src", "tests"] } diff --git a/packages/webapp/package.json b/packages/webapp/package.json index 784ae70ce1..162241467d 100644 --- a/packages/webapp/package.json +++ b/packages/webapp/package.json @@ -1,6 +1,6 @@ { "name": "litefarm-webapp", - "version": "3.12.0", + "version": "3.12.1", "description": "LiteFarm Web application", "type": "module", "devEngines": { @@ -95,8 +95,8 @@ "redux-saga": "^1.2.1", "reselect": "^4.1.7", "rrule": "2.7.2", - "survey-core": "^2.5.1", - "survey-react-ui": "^2.5.1", + "survey-core": "2.5.30", + "survey-react-ui": "2.5.30", "terra-draw": "1.28.8", "terra-draw-google-maps-adapter": "^1.3.1", "uuid": "^8.3.2", diff --git a/packages/webapp/pnpm-lock.yaml b/packages/webapp/pnpm-lock.yaml index 857b032ae0..e26a23b57e 100644 --- a/packages/webapp/pnpm-lock.yaml +++ b/packages/webapp/pnpm-lock.yaml @@ -208,11 +208,11 @@ importers: specifier: 2.7.2 version: 2.7.2 survey-core: - specifier: ^2.5.1 - version: 2.5.1 + specifier: 2.5.30 + version: 2.5.30 survey-react-ui: - specifier: ^2.5.1 - version: 2.5.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(survey-core@2.5.1) + specifier: 2.5.30 + version: 2.5.30(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(survey-core@2.5.30) terra-draw: specifier: 1.28.8 version: 1.28.8(patch_hash=c526b1c765b2c0b13051b01551ec0d74488cf6850ad30db2e8b7667f159eb2d2) @@ -6771,15 +6771,15 @@ packages: resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} engines: {node: '>= 0.4'} - survey-core@2.5.1: - resolution: {integrity: sha512-BiGkP/pK+MiTAhd86h6XtgAmgC4jTdUE7zLHp8dkrGFBSHQOhPkQs8ciif9YMI31MilqVPS43trwLdxMytwwjw==} + survey-core@2.5.30: + resolution: {integrity: sha512-lGwAPkMisfSkctd0wLMqSsNCFpzR34IVeEN1/JLdE1Bt20ruNBNSIR5OR7QHslHXT/vMflKlpNmb+VL3BJxyJA==} - survey-react-ui@2.5.1: - resolution: {integrity: sha512-0jsy7arRXA2UiLzEHfFHUIeWBzcfXDisFyLBj8Ed4jeofHtc8XkYNXYsKcky2HSIjp9mocRnnJr3KzzeqeFJtQ==} + survey-react-ui@2.5.30: + resolution: {integrity: sha512-DWlvpgdF8udMFkZISOEplXhrMpHNrzqcTx1CAtZFbwdW5AQocSezqiPDTJVYQkZJGVrYVdo7Bs1IqZqoBriEyQ==} peerDependencies: react: ^16.5.0 || ^17.0.1 || ^18.1.0 || ^19.0.0 react-dom: ^16.5.0 || ^17.0.1 || ^18.1.0 || ^19.0.0 - survey-core: 2.5.1 + survey-core: 2.5.30 svg-parser@2.0.4: resolution: {integrity: sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ==} @@ -15466,13 +15466,13 @@ snapshots: supports-preserve-symlinks-flag@1.0.0: {} - survey-core@2.5.1: {} + survey-core@2.5.30: {} - survey-react-ui@2.5.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(survey-core@2.5.1): + survey-react-ui@2.5.30(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(survey-core@2.5.30): dependencies: react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - survey-core: 2.5.1 + survey-core: 2.5.30 svg-parser@2.0.4: {} diff --git a/packages/webapp/public/locales/en/common.json b/packages/webapp/public/locales/en/common.json index ede933abf1..8256d80063 100644 --- a/packages/webapp/public/locales/en/common.json +++ b/packages/webapp/public/locales/en/common.json @@ -26,6 +26,7 @@ "CLICK_TO_ENLARGE": "Click to enlarge", "CLONE": "Clone", "CLOSE": "Close", + "COMPLETED": "Completed", "CONFIRM": "Confirm", "CONFIRM_AND_PUBLISH": "Confirm and Publish", "CONTINUE": "Continue", diff --git a/packages/webapp/public/locales/en/translation.json b/packages/webapp/public/locales/en/translation.json index 9f42aded17..b46c725e8d 100644 --- a/packages/webapp/public/locales/en/translation.json +++ b/packages/webapp/public/locales/en/translation.json @@ -1175,6 +1175,9 @@ "SPECIES_COUNT_other": "{{count}} species", "TITLE": "Biodiversity" }, + "CATHI_GAO": { + "TITLE": "Cathi-Gao Research Project" + }, "CLICK_TO_CALCULATE": "Click to calculate", "CURRENT": "Current", "INFO": "Insights provides added data insights into what is happening on your farm. The more data you provide in the application, the more insights can be generated. See individual insights for further information.", @@ -1201,6 +1204,10 @@ "INFO": "Soil organic matter is needed to maintain a healthy soil environment for your crops. We populate this insight from your most recent soil analysis task results. If you do not have any data we predict the potential soil organic matter for your location globally.", "TITLE": "Soil OM" }, + "SURVEY": { + "THANK_YOU": "Thank you. Your responses have been recorded.", + "TITLE": "Survey" + }, "TAPE": { "COMPLETED": "Completed - See your results", "IN_PROGRESS": "In progress", diff --git a/packages/webapp/public/locales/km/animal.json b/packages/webapp/public/locales/km/animal.json new file mode 100644 index 0000000000..e1f561a4d3 --- /dev/null +++ b/packages/webapp/public/locales/km/animal.json @@ -0,0 +1,69 @@ +{ + "BREED": { + "ANGUS": "ពូជគោសាច់ស្កុតឡែន អែងហ្គឹស", + "CHAROLAIS": "ពូជគោសាច់បារាំង​​​ ឆារ៉ូឡែស", + "COBB_500": "ពូជមាន់សាច់ កូប 500", + "CORNISH_CROSS": "ពូជមាន់សាច់ ខនិសក្រោះ", + "DUROC": "ពូជជ្រូក ឌុរុក", + "HEREFORD": "ពូជគោសាច់អង់គ្លេស ហៀហ្វដ", + "LANDRACE": "ពូជជ្រូក ឡេនដ្រាស", + "LEGHORN": "ពូជមាន់ ឡេហន់", + "PLYMOUTH_ROCK": "ពូជមាន់ ផ្លីមុតរ៉ក", + "RHODE_ISLAND_RED": "ពូជមាន់ រ៉ុតអាយឡេនរ៉េត", + "ROSS_308": "ពូជមាន់សាច់ រ៉ស់ 308", + "YORKSHIRE_LARGE_WHITE": "ពូជជ្រូកសាច់យ៉កសៀធំស" + }, + "ORIGIN": { + "BORN_AT_FARM": "កើតនៅកសិដ្ឋាន", + "BROUGHT_IN": "យកមកពីខាងក្រៅ" + }, + "PURPOSE": { + "GRAZING": "ការស៊ីស្មៅ", + "MILKING": "ការច្របាច់ទឹកដោះ", + "MANURE_MANAGEMENT": "ការគ្រប់គ្រងលាមកសត្វ", + "PEST_OR_DISEASE_CONTROL": "ការគ្រប់គ្រងសត្វល្អិត ឬជំងឺ", + "BREEDING": "ការបង្កាត់ពូជ", + "FEEDING": "ឲចំណី", + "VETERINARY_CARE": "ការថែទាំសុខភាពសត្វ", + "BIRTHING": "ការបង្កើតកូន", + "WEANING": "ការផ្តាច់ដោះ", + "TRANSPORTATION": "ការដឹកជញ្ជូន", + "BEHAVIORAL_AND_SOCIAL_MANAGEMENT": "ការគ្រប់គ្រងអាកប្បកិរិយា និងសង្គម", + "EXERCISE": "លំហាត់", + "QUARANTINE": "ការដាក់ឲ្យនៅដាច់ដោយឡែក", + "OTHER": "ផ្សេងទៀត" + }, + "SEX": { + "MALE": "ប្រុស", + "FEMALE": "ស្រី" + }, + "TAG_COLOR": { + "BLUE": "ខៀវ", + "GREEN": "បៃតង", + "ORANGE": "ទឹកក្រូច", + "RED": "ក្រហម", + "WHITE": "ស", + "YELLOW": "លឿង" + }, + "TAG_TYPE": { + "EAR_TAG": "ប័ណ្ណសម្គាល់នៅត្រចៀកសត្វ", + "LEG_BAND": "ស្លាកពាក់ជើងសត្វ" + }, + "TYPE": { + "CATTLE": "គោក្របី", + "CHICKEN": "មាន់", + "PIGS": "ជ្រូក" + }, + "USE": { + "MILK": "ទឹកដោះគោ", + "EGGS": "ស៊ុត", + "FAT": "ខ្លាញ់", + "MEAT": "សាច់", + "ANIMAL_FIBERS_AND_SKINS": "សរសៃ និងស្បែកសត្វ", + "LABOUR_AND_DRAFT": "កម្លាំងពលកម្ម និងការទាញ/ដឹក", + "BREEDING": "ការបង្កាត់ពូជ", + "RECREATIONAL_OR_CULTURAL_USE": "ការប្រើប្រាស់សម្រាប់កម្សាន្ត ឬវប្បធម៌", + "COMPANIONSHIP": "ភាពជាដៃគូ", + "OTHER": "ផ្សេងទៀត" + } +} diff --git a/packages/webapp/public/locales/km/certifications.json b/packages/webapp/public/locales/km/certifications.json new file mode 100644 index 0000000000..3c7665d519 --- /dev/null +++ b/packages/webapp/public/locales/km/certifications.json @@ -0,0 +1,4 @@ +{ + "THIRD_PARTY_ORGANIC": "ធាតុសរីរាង្គដែលបានបញ្ជាក់ដោយភាគីទីបី", + "PGS": "ប្រព័ន្ធធានាគុណភាពដោយការចូលរួម" +} diff --git a/packages/webapp/public/locales/km/common.json b/packages/webapp/public/locales/km/common.json new file mode 100644 index 0000000000..d3e495abd5 --- /dev/null +++ b/packages/webapp/public/locales/km/common.json @@ -0,0 +1,128 @@ +{ + "ABANDON": "បោះបង់", + "ACTIVE": "សកម្ម", + "ADD": "បន្ថែម", + "ADD_ANOTHER_ITEM": "បន្ថែមធាតុមួយទៀត", + "ADD_ITEM": "បន្ថែមធាតុ {{itemName}}", + "ADD_TO_GROUP": "បន្ថែមទៅក្រុម", + "AGE": "អាយុ", + "AGE_DAYS_COUNT_one": "{{count}} ថ្ងៃ", + "AGE_DAYS_COUNT_other": "{{count}} ថ្ងៃ", + "AGE_MONTHS_COUNT_one": "{{count}} ខែ", + "AGE_MONTHS_COUNT_other": "{{count}} ខែ", + "AGE_YEARS_COUNT_one": "{{count}} ឆ្នាំ", + "AGE_YEARS_COUNT_other": "{{count}} ឆ្នាំ", + "ALL": "ទាំងអស់", + "AMOUNT": "បរិមាណ", + "AND": "និង", + "APPLY": "អនុវត្ត / ប្រើប្រាស់", + "APPROVE": "យល់ព្រម", + "BACK": "ត្រឡប់ក្រោយ", + "CANCEL": "លុបចោល", + "CHANGE": "ផ្លាស់ប្តូរ", + "CHAR_LIMIT_ERROR": "កំណត់ចំនួនតួអក្សរអតិបរមា {{value}}", + "CLEAR_ACTIVE_FILTERS": "លុបកំរងទិន្នន័យសកម្ម", + "CLEAR_SELECTION": "លុបផ្នែករជ្រើសរើសទាំងអស់", + "CLICK_TO_ENLARGE": "ចុចដើម្បីពង្រើក", + "CLONE": "ចម្លងទាំងស្រុង", + "CLOSE": "បិទ", + "CONFIRM": "បញ្ជាក់ព័ត៌មាន", + "CONFIRM_AND_PUBLISH": "បញ្ជាក់ និងបោះផ្សាយ", + "CONTINUE": "បន្ត", + "COPY_OF": "ថតចម្លង​​ ​{{item}}", + "COUNT": "រាប់", + "CREATE": "បង្កើត", + "CREATE_A_TASK": "បង្កើតកិច្ចការ", + "DATE": "កាលបរិច្ឆេទ", + "DELETE": "លុប", + "DO_NOT_KNOW": "ខ្ញុំមិនដឹងទេ", + "DO_NOT_SHOW": "កុំបង្ហាញសារនេះម្ដងទៀត។", + "DONE": "រួចរាល់", + "DUPLICATING": "កំពុងបង្កើតច្បាប់ចម្លង...", + "EDIT": "កែ", + "EDIT_DATE": "កែកាលបរិច្ឆេទ", + "EDITING": "កំពុងកែ...", + "EMAIL": "អុីមែល", + "ENTER_VALUE": "បញ្ចូលតំលៃ", + "EXPORT": "នាំចេញ", + "FETCHING_YOUR_DATA": "សូមរង់ចាំខណៈប្រព័ន្ធកំពុងទាញយកទិន្នន័យ {{dataName}} របស់អ្នក", + "FINISH": "បញ្ចប់", + "FROM": "ពី", + "GO_BACK": "ត្រឡប់ក្រោយ", + "GOT_IT": "ទទួលបានហើយ!", + "HERE": "ទីនេះ", + "INVALID_DATE": "កាលបរិច្ឆេទមិនត្រឹមត្រូវ", + "LOADING": "កំពុងដំណើរការ...", + "MANAGE_ENTITY": "គ្រប់គ្រង ​{{entity}}", + "MARK_ABANDON": "បោះបង់", + "MARK_COMPLETE": "សម្គាល់បញ្ចប់", + "MARK_COMPLETED": "សម្គាល់ថាបានបញ្ចប់", + "MAX_CHARS": "កំណត់ចំនួនតួអក្សរអតិបរមា ​{{value}}", + "MAX_ERROR": "សូមបញ្ចូលតំលៃតិចជាង ​{{value}}", + "MIN_ERROR": "សូមបញ្ចូលតំលៃច្រើនជាង {{value}}", + "NAME": "ឈ្មោះ", + "NEEDS_PLAN": "ត្រូវការផែនការ", + "NEXT": "បន្ទាប់", + "NO": "ទេ", + "NO_OPTIONS": "គ្មានជម្រើស", + "NON_ORGANIC": "មិនមែនជាសរីរាង្គ", + "NONE": "មិនមាន", + "NOT_SURE": "មិនប្រាកដ", + "NOTES": "កំនត់ចំណាំ", + "OK": "យល់ព្រម", + "OPTIONAL": "មិនចាំប៉ាច់​​ /ធ្វើឬមិនធ្វើក៏បាន", + "OR": "ឬ", + "ORGANIC": "សរីរាង្គ", + "OTHER": "ផ្សេងទៀត", + "PAST": "អតីតកាល", + "PLANNED": "មានផែនការ", + "PREVIOUS": "ពីមុន", + "PRICE": "តម្លៃ", + "PROBABILITY": "ប្រូបាប៊ីលីតេ​​ /ឱកាសកើតឡើង", + "PROCEED": "បន្ត", + "PROPERTY_UNKNOWN": "មិនស្គាល់​ {{property}}", + "QUANTITY": "បរិមាណ", + "REMOVE": "ដកចេញ", + "REMOVE_ITEM": "ដកចេញធាតុ", + "REMOVED": "ដកចេញ", + "REQUIRED": "ត្រូវការ", + "RETIRE": "ចូលនិវត្តន៍", + "REVISION_INFO": "បានកែប្រែនៅថ្ងៃទី​​ {{date}} ដេាយ {{user}}", + "SAVE": "រក្សាទុក", + "SAVE_CHANGES": "រក្សាទុកការផ្លាស់ប្តូរ", + "SEARCH": "ស្វែងរក", + "SEE_ON_MAP": "មើលលើផែនទី", + "SELECT": "ជ្រើសរើស", + "SELECT_ALL": "ជ្រើសរើសទាំងអស់", + "SELECT_OR_ADD_YOUR_OWN": "ជ្រើសរើស​រឺបន្ថែមចំនុចផ្ទាល់ខ្លួន", + "SELECTED_COUNT": "{{count}} បានជ្រើសរើស", + "SELECTED_COUNT_one": "{{count}} បានជ្រើសរើស", + "SELECTED_COUNT_many": "{{count}} បានជ្រើសរើស", + "SELECTED_COUNT_other": "{{count}} បានជ្រើសរើស", + "SET": "កំណត់", + "SHARE": "ចែករំលែក", + "SHOWING_ALL": "បង្ហាញទាំងអស់", + "SKIP": "រំលង", + "SORRY": "សុំទោស​", + "SUBMIT": "បញ្ជូន", + "SUBMITTING": "កំពុងបញ្ជូន...", + "SUGGEST": "ស្នើសុំ", + "THATS_FINE": "ដំណើរការល្អ", + "TODAY": "ថ្ងៃនេះ", + "TOTAL": "សរុប", + "TRANSITIONING": "កំពុងផ្លាស់ប្តូរ", + "TYPE": "ប្រភេទ", + "TYPES": "ប្រភេទ", + "UNIT": "ឯកតា", + "UNKNOWN": "មិនស្គាល់", + "UPDATE": "ធ្វើបច្ចុប្បន្នភាព", + "UPLOAD": "ផ្ទេរទិន្នន័យឡើងទៅអ៊ីនធឺណិត", + "UPLOADING": "កំពុងផ្ទេរទិន្នន័យឡើងទៅអ៊ីនធឺណិត...", + "USE": "ប្រើប្រាស់", + "VOLUME": "ចំណុះ/បរិមាណ", + "WEIGHT": "ទម្ងន់", + "WORD_LIMIT_ERROR": "បង្ហាញបានត្រឹមតែ {{value}} តួអក្សរ", + "YEAR": "ឆ្នាំ", + "YES": "បាទ​ / ចាស", + "YESTERDAY": "ម្សិលមិញ" +} diff --git a/packages/webapp/public/locales/km/crop.json b/packages/webapp/public/locales/km/crop.json new file mode 100644 index 0000000000..8341909c1d --- /dev/null +++ b/packages/webapp/public/locales/km/crop.json @@ -0,0 +1,490 @@ +{ + "ABACA_MANILA_HEMP": "រុក្ខជាតិអាបាកា (សរសៃរុក្ខជាតិ​ម៉ានីល)", + "ALFALFA_FOR_FODDER": "រុក្ខជាតិអាល់ហ្វាល់ហ្វា សម្រាប់ធ្វើជាចំណីសត្វ", + "ALFALFA_FOR_SEED": "អាល់ហ្វាល់ហ្វា សម្រាប់គ្រាប់ពូជ", + "ALMOND": "គ្រាប់អាល់ម៉ុន", + "ANISE_SEEDS": "គ្រាប់រុក្ខជាតិអានីស", + "APPLE": "ផ្លែប៉ោម", + "APRICOT": "ផ្លែអាប្រិកូត", + "ARECA_BETEL_NUT": "ដើមអារេកា (គ្រាប់ស្លា)", + "ARRACHA": "ដំណាំឫសអារ៉ាឆាកា", + "ARROWROOT": "ឫសអារ៉ូរូត", + "ARTICHOKE": "ផ្កាអាតិចុក", + "ASPARAGUS": "ទំពាំងបារាំង", + "AVOCADO": "ផ្លែប័រ", + "BAJRA_PEARL_MILLET": "បាច្រា (ស្រូវមីលែតគ្រាប់តូច)", + "BAMBARA_GROUNDNUT": "សណ្ដែកបាំបារ៉ា", + "BANANA": "ចេក", + "BARLEY": "ស្រូវបារលី", + "BEANS": "សណ្តែក", + "BEANS_DRY_EDIBLE_FOR_GRAINS": "សណ្តែកស្ងួតអាចបរិភោគសម្រាប់យកគ្រាប់", + "BEANS_HARVESTED_GREEN": "សណ្តែកប្រមូលផលខ្ចី", + "BEET": "ឫសប៊ីត", + "BEET_FODDER_MANGEL": "ឫសប៊ីតសម្រាប់ធ្វើចំណីសត្វ (ម៉ង់ហ្គែល)", + "BEET_RED": "ឫសប៊ីត ក្រហម", + "BEET_SUGAR": "ឫសប៊ីត ស្ករ", + "BEET_SUGAR_FOR_FODDER": "ឫសប៊ីតស្ករសម្រាប់ធ្វើចំណីសត្វ", + "BEET_SUGAR_FOR_SEEDS": "ឫសប៊ីតស្ករសម្រាប់គ្រាប់ពូជ", + "BERGAMOT": "ក្រូចប៊ឺកាម៉ូត", + "BLACKBERRIES_": "ផ្លែប៊្លែកប៊ែរី", + "BLACKBERRIES_OF_VARIOUS_SPECIES": "ផ្លែប៊្លែកប៊ែរីប្រភេទផ្សេងៗគ្នា", + "BLACK_PEPPER": "ម្រេចខ្មៅ", + "BLACK_WATTLE": "អាកាស្យាខ្មៅ", + "BLUEBERRY": "ផ្លែប្លូប៊ែរី", + "BRAZIL_NUT": "គ្រាប់ប្រេស៊ីល", + "BREADFRUIT": "ផ្លែប្រេដហ្វ្រូត", + "BROAD_BEAN": "សណ្តែកហ្វាវ៉ា", + "BROAD_BEAN_DRY": "សណ្តែកហ្វាវ៉ាស្ងួត", + "BROAD_BEAN_HARVESTED_GREEN": "សណ្តែកហ្វាវ៉ាស្ងួត​ ប្រមូលផលនៅខ្ចី", + "BROCCOLI": "ប្រូខូលី", + "BROOM_MILLET": "ស្រូវមីលែត", + "BROOM_SORGHUM": "ស្រូវសូហ្គាំ", + "BRUSSELS_SPROUTS": "ស្ពៃប្រ៊ុសសែល", + "BUCKWHEAT": "ស្រូវបាក់វីត", + "CABBAGE": "ស្ពៃក្តោប", + "CABBAGE_CHINESE": "ស្ពៃបូកគោ", + "CABBAGE_FOR_FODDER": "ស្ពៃក្តោប សម្រាប់ធ្វើចំណីសត្វ", + "CABBAGE_RED_WHITE_SAVOY": "ស្ពៃក្តោប​ (ក្រហម ស​ សាវ៉យ)", + "CACAO_COCOA": "កាកាវ (កាកាវ)", + "CANTALOUPE": "ផ្លែកានតាលូប", + "CARAWAY_SEEDS": "គ្រាប់កាឡាវេ", + "CARDAMOM": "ក្រវាញ", + "CARDOON": "ដើមកាដូន", + "CAROB": "ផ្លែការ៉ូប", + "CARROT": "ការ៉ុត", + "CARROT_EDIBLE": "ការ៉ុតសម្រាប់បរិភោគ", + "CARROT_FOR_FODDER": "ការ៉ុតសម្រាប់ចំណីសត្វ", + "CASHEW_NUTS": "គ្រាប់ស្វាយចន្ទី", + "CASSAVA_MANIOC": "ដំឡូងមី ​(មែនីអុក)", + "CASTOR_BEAN": "គ្រាប់ល្ហុងប្រេង", + "CAULIFLOWER": "ផ្កាខាត់ណា", + "CELERIAC": "មើមវ៉ាន់ស៊ុយបារាំង សេឡេរីអាក់", + "CELERY": "វ៉ាន់ស៊ុយ", + "CHAYOTE": "ផ្លែស៊ូ", + "CHERRY_ALL_VARIETIES": "ផ្លែឈឺរី (គ្រប់ប្រភេទ)", + "CHESTNUT": "គ្រាប់ឈេសណាត់", + "CHICKPEA_GRAM_PEA": "សណ្តែកសៀងសំបកជ្រីវជ្រួញ (សណ្តែកឈីកភី)", + "CHICORY": "ដើមឈីកូរី", + "CHICORY_FOR_GREENS": "ដើមឈីកូរីសម្រាប់យកស្លឹកបន្លែ", + "CHILI_ALL_VARIETIES": "ម្ទេស (គ្រប់ប្រភេទ)", + "CHILI_DRY_ALL_VARIETIES": "ម្ទេសគ្រៀម (គ្រប់ប្រភេទ)", + "CHILI_FRESH_ALL_VARIETIES": "ម្ទេសស្រស់ (គ្រប់ប្រភេទ)", + "CINNAMON": "សម្បកឈើអែម", + "CITRON": "ផ្លែក្រូចឃ្វិចធំ", + "CITRONELLA": "ស្លឹកគ្រៃក្រអូប", + "CLEMENTINE": "ផ្លែក្រូចឃ្វិចក្លេម៉ង់ទីន", + "CLOVE": "ផ្កាក្លាំពូ", + "CLOVER": "ស្មៅក្លូវើ", + "CLOVER_FOR_FODDER_ALL_VARIETIES": "ស្មៅក្លូវើសម្រាប់ចំណីសត្វ (គ្រប់ប្រភេទ)", + "CLOVER_FOR_SEED_ALL_VARIETIES": "ស្មៅក្លូវើសម្រាប់យកគ្រាប់ពូជ (គ្រប់ប្រភេទ)", + "COCOA_CACAO": "កាកាវ (កាកាវ)", + "COCONUT": "ផ្លែដូង", + "COCOYAM": "ដំឡូងត្រាវព្រៃ", + "COFFEE": "កាហ្វេ", + "COLA_NUT_ALL_VARIETIES": "គ្រាប់កូឡា (គ្រប់ប្រភេទ)", + "COLZA_RAPESEED": "គ្រាប់កុលហ្សា (រ៉ាប់ស៊ីត)", + "CORN_FOR_SALAD": "ពោតសម្រាប់ធ្វើសាឡាត់", + "CORN_MAIZE_FOR_CEREALS": "ពោតសម្រាប់ធ្វើធញ្ញជាតិ (ពោត)", + "CORN_MAIZE_FOR_SILAGE": "ពោតសម្រាប់ធ្វើចំណីផ្អាប់សត្វ (ពោត)", + "CORN_SWEET_FOR_VEGETABLE": "ពោត(ផ្អែម)សម្រាប់ធ្វើបន្លែ", + "COTTONSEED_ALL_VARIETIES": "គ្រាប់កប្បាស (គ្រប់ប្រភេទ)", + "COTTON_ALL_VARIETIES": "ដើមកប្បាស (គ្រប់ប្រភេទ)", + "COWPEA": "សណ្តែកអង្គុយ", + "COWPEA_FOR_GRAIN": "សណ្តែកអង្គុយសម្រាប់យកគ្រាប់", + "COWPEA_HARVESTED_GREEN": "សណ្តែកអង្គុយប្រមូលផលទាំងខៀវ", + "CRANBERRY": "ផ្លែគ្រែនប៊ឺរី", + "CRESS": "បន្លែគ្រេស", + "CUCUMBER": "ត្រសក់", + "CURRANTS_ALL_VARIETIES": "ផ្លែការ៉ង់ (គ្រប់ប្រភេទ)", + "CUSTARD_APPLE": "ផ្លែទៀប", + "DASHEEN": "ដំឡូងត្រាវដាស៊ីន", + "DATES": "ផ្លែល្មើ", + "DRUMSTICK_TREE": "ដើមម្រុំ", + "DURRA_SORGHUM": "ស្មៅឌូរ៉ា ​(ស៊ើហ្គុម)", + "DURUM_WHEAT": "ស្រូវសាលីឌូរុាំ", + "EARTH_PEA": "សណ្តែកដីអាហ្វ្រិក", + "EDO_EDDOE": "មើមត្រាវតូច (អេដូ)", + "EGGPLANT": "ផ្លែត្រប់វែង", + "ENDIVE": "បន្លែអង់ឌីវ", + "FENNEL": "មើមហ្វេនណល", + "FENUGREEK": "គ្រាប់ហ្វេនូហ្គ្រីក", + "FIG": "ផ្លែល្វា", + "FILBERT_HAZELNUT": "គ្រាប់ហ្វិលបឺត​(ហេសិលណាត់)", + "FIQUE": "សរសៃហ្វិក", + "FLAX_": "ដើមផ្លាក់ស៍", + "FLAX_FOR_FIBRE": "ដើមផ្លាក់ស៍សម្រាប់យកសរសៃអំបោះ", + "FLAX_FOR_OIL_SEED_LINSEED": "គ្រាប់ផ្លាក់ស៍សម្រាប់យកប្រេង (គ្រាប់លីនស៊ិត)", + "FORMIO_NEW_ZEALAND_FLAX": "ដើមហ្វរមីអូ (ផ្លាក់ស៍ញូវហ្សីឡែន)", + "GARLIC": "ខ្ទឹមស", + "GARLIC_DRY": "ខ្ទឹមសស្ងួត", + "GARLIC_GREEN": "ដើមខ្ទឹមសស្រស់", + "GERANIUM": "ផ្កាហ្សេរ៉ានីញ៉ូម", + "GINGER": "ខ្ញី", + "GOOSEBERRY_ALL_VARIETIES": "ហ្គូសប៊ឺរី (គ្រប់ប្រភេទ)", + "GOURD": "ផ្លែឃ្លោក", + "GOURD_AFRICAN": "ឃ្លោក(អាហ្វ្រិក)", + "GOURD_AMERICAN": "ឃ្លោក(អាមេរិក)", + "GRAM_PEA_CHICKPEA": "សណ្តែក(ឈីកភី)", + "GRAPE": "ផ្លែទំពាំងបាយជូរ", + "GRAPEFRUIT": "ផ្លែក្រូចថ្លុងអាមេរិក", + "GRAPES_": "ផ្លែទំពាំងបាយជូរ", + "GRAPES_FOR_RAISINS": "ទំពាំងបាយជូរសម្រាប់ធ្វើទំពាំងបាយជូរក្រៀម", + "GRAPES_FOR_TABLE_USE": "ទំពាំងបាយជូរសម្រាប់ហូបស្រស់", + "GRAPES_FOR_WINE": "ទំពាំងបាយជូរសម្រាប់ធ្វើស្រា", + "GRASS_ESPARTO": "ស្មៅអែសប៉ាតូ", + "GRASS_ORCHARD": "ស្មៅចំណីសត្វ", + "GRASS_SUDAN": "ស្មៅស៊ូដង់", + "GROUNDNUT_PEANUT": "សណ្តែកដី (សណ្តែកដី)", + "GUAVA": "ផ្លែត្របែក", + "GUINEA_CORN_SORGHUM": "ស្មៅហ្គីណេ (ស៊ើហ្គុម)", + "HAZELNUT_FILBERT": "គ្រាប់ហេសិលណាត់​ (ហ្វិលបឺត)", + "HEMPSEED": "គ្រាប់ហិមស៊ិត", + "HEMP_": "ដើមកញ្ឆង់", + "HEMP_FIBRE": "សរសៃកញ្ឆង់", + "HEMP_MANILA_ABACA": "កញ្ឆាម៉ានីល (អាបាកា)", + "HEMP_SUN": "ដើមសណ្តែកជួរ", + "HEN": "មេមាន់", + "HENEQUEN": "ដើមហេណេគិន", + "HOP": "ផ្កាហប", + "HOPS": "ផ្កាហប", + "HORSERADISH": "មើមរ៉ាឌីហ្សហឹរ", + "HORSE_BEAN": "សណ្តែកធំប្រភេទម្យ៉ាង", + "HYBRID_MAIZE": "ពោតកាត់", + "INDIGO": "ដើមធ្មង់", + "JASMINE": "ផ្កាម្លិះ", + "JERUSALEM_ARTICHOKE": "ដំឡូងជេរូសាឡឹមអាតិកុក", + "JOWAR_SORGHUM": "ស្មៅចូឡា(ស៊ើហ្គុម)", + "JUTE": "ដើមក្រចៅ", + "KALE": "ស្ពៃខេល", + "KAPOK": "ដើមគរ", + "KENAF": "ដើមកញ្ចៅព្រៃ", + "KOHLRABI": "មើមស្ពៃក្តោបកូឡរ៉ាប៊ី", + "LAVENDER": "ផ្កាឡាវិនឌើ", + "LEEK": "ខ្ទឹមខ្យល់", + "LEMON": "ផ្លែក្រូចឆ្មារលឿង", + "LEMON_GRASS": "ស្លឹកគ្រៃ", + "LENTIL": "សណ្តែកឡង់ទីល", + "LESPEDEZA_ALL_VARIETIES": "ស្មៅឡែស្បឺឌីហ្សា (គ្រប់ប្រភេទ)", + "LETTUCE": "សាឡាត់", + "LIME": "ក្រូចឆ្មារ", + "LIME_SOUR": "ក្រូចឆ្មារជូរ", + "LIME_SWEET": "ក្រូចឆ្មារផ្អែម", + "LINSEED_FLAX_FOR_OIL_SEED": "គ្រាប់លីនស៊ិត (គ្រាប់ផ្លាក់ស៍យកប្រេង)", + "LIQUORICE": "ដើមអែមចិនលីកូរីស", + "LITCHI": "ផ្លែគូលែន", + "LOQUAT": "ផ្លែឡូក្វាត", + "LUPINE_ALL_VARIETIES": "ផ្កាលូភីន (គ្រប់ប្រភេទ)", + "MACADAMIA_NUT": "គ្រាប់ម៉ាកាដាមៀ", + "MACADAMIA_QUEENSLAND_NUT": "គ្រាប់ម៉ាកាដាមៀ (គ្រាប់ឃ្វីនស៍ឡែន)", + "MACE": "សំបកចន្ទន៍ទេស", + "MAGUEY": "ដើមប្រទាលម៉ាហ្ហ្គី", + "MAIZE_CORN": "ពោត ​​(ពោត)", + "MAIZE_CORN_FOR_SILAGE": "ពោតសម្រាប់ធ្វើចំណីផ្អាប់សត្វ ​​(ពោត)", + "MAIZE_GRAIN": "គ្រាប់ពោត ​​(ពោត)", + "MAIZE_HYBRID": "ពោត(ពូជកាត់)", + "MAIZE_ORDINARY": "ពោតធម្មតា", + "MAIZE_SWEET_CORN": "ពោតផ្អែម​​​​ (ពោត)", + "MANDARIN": "ផ្លែក្រូចឃ្វិច", + "MANGEL_FODDER_BEET": "មើមប៊ីតម៉ង់ហ្គែល ​(មើមសម្រាប់ចំណីសត្វ)", + "MANGO": "ស្វាយ", + "MANIOC_CASSAVA": "មែនីអុក (ដំឡូងមី)", + "MASLIN_MIXED_CEREALS": "ធញ្ញជាតិម៉ាសលីន (ធញ្ញជាតិលាយឡំ)", + "MEDLAR": "ផ្លែម៉េដឡា", + "MELON_": "ផ្លែត្រសក់ផ្អែមមីឡុង", + "MELON_EXCEPT_WATERMELON": "ផ្លែត្រសក់ផ្អែមមីឡុង(លើកលែងផ្លែតែឪឡឹក)", + "MILLET_BAJRA": "ស្មៅមីល្លីតបាចរ៉ា", + "MILLET_BAJRA_PEARL": "ស្មៅមីល្លីត(បាចរ៉ាគ្រាប់គុជ)", + "MILLET_BROOM": "ស្មៅមីល្លីត(ប្រូម)", + "MILLET_BULRUSH": "ស្មៅមីល្លីត (ប៊ុលរ៉ាស់)", + "MILLET_FINGER": "ស្មៅមីល្លីត (ម្រាមដៃ)", + "MILLET_FOXTAIL": "ស្មៅមីល្លីត (កន្ទុយកញ្ជ្រោង)", + "MILLET_JAPANESE": "ស្មៅមីល្លីត (ជប៉ុន)", + "MILLET_PEARL_BAJRA_BULRUSH": "ស្មៅមីល្លីតគ្រាប់គុជ (បាចរ៉ា ប៊ុលរ៉ាស់)", + "MILLET_PROSO": "ស្មៅមីល្លីត(ប្រូសូ)", + "MINT_ALL_VARIETIES": "ជីអង្កាម (គ្រប់ប្រភេទ)", + "MULBERRY_ALL_VARIETIES": "ដើមមន (គ្រប់ប្រភេទ)", + "MULBERRY_FOR_FRUIT_ALL_VARIETIES": "ដើមមនម្រាប់ផ្លែ (គ្រប់ប្រភេទទាំងអស់)", + "MULBERRY_FOR_SILKWORMS": "ដើមមនសម្រាប់ចិញ្ចឹមដង្កូវនាង", + "MUSHROOMS": "ផ្សិត", + "MUSTARD": "ស្ពៃខៀវ", + "MUSTARD_FOR_SEED": "ស្ពៃខៀវយកគ្រាប់", + "NECTARINE": "ផ្លែណិចតារីន", + "NIGER_SEED": "គ្រាប់នីហ្សឺ", + "NUTMEG": "ផ្លែចន្ទន៍ទេស", + "OATS": "ស្រូវអូត", + "OATS_FOR_FODDER": "ស្រូវអូតសម្រាប់ចំណីសត្វ", + "OATS_FOR_GRAIN": "ស្រូវអូតសម្រាប់យកគ្រាប់ធញ្ញជាតិ", + "OIL_PALM": "ដើមដូងប្រេង", + "OKRA": "ផ្លែពោតបារាំង", + "OLIVE": "ផ្លែអូលីវ", + "ONION": "ខ្ទឹមបារាំង", + "ONION_DRY": "ខ្ទឹមបារាំងក្រៀម", + "ONION_GREEN": "ខ្ទឹមបារាំងបៃតង", + "ONION_SEED": "គ្រាប់ពូជខ្ទឹមបារាំង", + "OPIUM": "អាភៀន", + "ORANGE": "ក្រូច", + "ORANGE_BITTER": "ក្រូច​(ល្វីង)", + "ORNAMENTAL_PLANTS": "រុក្ខជាតិលម្អ", + "PALM_KERNEL_OIL": "ប្រេងពីគ្រាប់ក្នុងដូងប្រេង", + "PALM_OIL": "ប្រេងដូងប្រេង", + "PALM_PALMYRA": "ដើមត្នោត", + "PALM_SAGO": "ដើមត្នោតសាវូ", + "PAPAYA_PAWPAW": "ផ្លែល្ហុង (ផៅផៅ)", + "PARSNIP": "ដើមត្នោតសាវូ", + "PEA": "មើមការ៉ុតសប៉ាសនីប", + "PEACH": "សណ្តែកមូល", + "PEANUT_GROUNDNUT": "សណ្តែកដី​ (សណ្តែកដី)", + "PEAR": "ផ្លែប៉ែស", + "PEA_EDIBLE_DRY_FOR_GRAIN": "សណ្តែកមូលស្ងួតសម្រាប់ហូបគ្រាប់", + "PEA_HARVESTED_GREEN": "សណ្តែកមូលប្រមូលផលទាំងខៀវ", + "PECAN_NUT": "គ្រាប់ភីកាន", + "PEPPER_BLACK": "ម្រេចខ្មៅ", + "PEPPER_DRY": "ម្រេចស្ងួត", + "PERSIMMON": "ផ្លែទន្លាប់", + "PERSIMMON_KAKI": "ផ្លែទន្លាប់​(កាគី)", + "PIGEON_PEA": "សណ្តែកគោក", + "PINEAPPLE": "ផ្លែម្នាស់", + "PISTACHIO_NUT": "គ្រាប់ពិស្តាឈីអូ", + "PLANTAIN": "ចេកស្នាប់មុខ", + "PLUM": "ផ្លែផ្លាំ", + "POMEGRANATE": "ផ្លែទទឹម", + "POMELO": "ផ្លែក្រូចថ្លុង", + "POPPY_SEED": "គ្រាប់ប៉បពី", + "POTATO": "ដំឡូងបារាំង", + "POTATO_SWEET": "ដំឡូងឈ្វា", + "PRUNE": "ផ្លែព្រូន", + "PUMPKIN": "ផ្លែល្ពៅ", + "PUMPKIN_EDIBLE": "ល្ពៅសំរាប់បរិភោគ", + "PUMPKIN_FOR_FODDER": "ល្ពៅសម្រាប់បរិភោគ", + "PYRETHUM": "ផ្កាប៉ៃរ៉េធិម", + "QUEBRACHO": "ដើមឃេប្រាកូ", + "QUEENSLAND_NUT": "គ្រាប់ឃ្វីនស៍ឡែន", + "QUINCE": "ផ្លែឃ្វីនស៍", + "QUININE": "ដើមកីនីន", + "QUINOA": "គ្រាប់គីណួ", + "RADISH": "មើមឆាយថាវ", + "RAMIE": "ដើមរ៉ាមី", + "RAPESEED_COLZA": "គ្រាប់រ៉ាប់ស៊ីតសម្រាប់ធ្វើប្រេង (កុលហ្សា)", + "RASPBERRY_ALL_VARIETIES": "ផ្លែរ៉ាសប៊ឺរី (គ្រប់ប្រភេទ)", + "REDTOP": "ស្មៅរ៉េដថប", + "RED_BEET": "មើមប៊ីតក្រហម", + "RHEA": "ដើមរ៉ា", + "RHUBARB": "ដើមរ៉ូបាប", + "RICE": "ស្រូវ", + "RICE_AFRICAN": "ស្រូវ​(អាហ្រ្វិក)", + "ROSE": "ផ្កាកុលាប", + "RUBBER": "មើមស្ពៃស៊ុយអែត", + "RUTABAGA_SWEDE": "មើមស្ពៃរ៉ុតាបាហ្គា(ស៊ុយអែត)", + "RYE": "ស្រូវរ៉ៃ", + "RYEGRASS_": "ស្មៅរ៉ៃហ្ហ្គ្រាស", + "RYEGRASS_SEED": "គ្រាប់ពូជស្មៅរ៉ៃហ្ហ្គ្រាស", + "SAFFLOWER": "ផ្កាឈរផ្អែមយកប្រេង", + "SAINFOIN": "ស្មៅសែនហ្វូញ", + "SALSIFY": "មើមសាលស៊ីហ្វី", + "SAPODILLA": "ផ្លែល្មុត", + "SATSUMA_MANDARIN/TANGERINE": "ក្រូចខ្វិចសាតស៊ូម៉ា​ (ថែងចើរិន)", + "SCORZONERA_BLACK_SALSIFY": "មើមសាលស៊ីហ្វីខ្មៅ", + "SESAME": "ល្ង", + "SHEA_BUTTER_NUT": "គ្រាប់ស៊ា (សម្រាប់ធ្វើប៊ឺស៊ា)", + "SISAL": "ប្រទាលស៊ីសាល់", + "SORGHUM": "ដើមស៊ើហ្គុម", + "SORGHUM_BROOM": "ដើមស៊ើហ្គុមសម្រាប់ធ្វើអំបោស", + "SORGHUM_DURRA": "ដើមស៊ើហ្គុមឌូរ៉ា", + "SORGHUM_GUINEA_CORN": "ដើមស៊ើហ្គុមហ្គីណេ", + "SORGHUM_JOWAR": "ដើមស៊ើហ្គុមចូឡា", + "SORGHUM_SWEET": "ដើមស៊ើហ្គុមផ្អែម", + "SOYBEAN": "សណ្តែកសៀង", + "SOYBEAN_HAY": "ចំបើងសណ្តែកសៀង", + "SPELT_WHEAT": "ស្រូវសាលីស្ពែលថ៍", + "SPINACH": "បន្លែពួយឡេង", + "SQUASH": "ល្ពៅអ៊ីតាលី", + "STRAWBERRY": "ផ្លែស្ត្រប៊ឺរី", + "SUGARCANE": "អំពៅ", + "SUGARCANE_FOR_FODDER": "អំពៅសម្រាប់ចំណីសត្វ", + "SUGARCANE_FOR_SUGAR_OR_ALCOHOL": "អំពៅសម្រាប់ផលិតស្ករឬអាល់កុល", + "SUGARCANE_FOR_THATCHING": "អំពៅសម្រាប់ប្រក់ដំបូល", + "SUGAR_BEET": "មើមប៊ីតស្ករ", + "SUGAR_BEET_FOR_FODDER": "មើមប៊ីតស្ករសម្រាប់ចំណីសត្វ", + "SUGAR_BEET_FOR_SEED": "មើមប៊ីតស្ករសម្រាប់យកគ្រាប់ពូជ", + "SUNFLOWER": "ផ្កាឈូករ័ត្ន", + "SUNFLOWER_FOR_FODDER": "ដើមផ្កាឈូករ័ត្នសម្រាប់ចំណីសត្វ", + "SUNFLOWER_FOR_OIL_SEED": "គ្រាប់ផ្កាឈូករ័ត្នសម្រាប់យកប្រេង", + "SUNHEMP": "សណ្តែកជួរសាន់ហិម", + "SWEDE": "មើមស្ពៃស៊ុយអែត", + "SWEDE_FOR_FODDER": "មើមស្ពៃស៊ុយអែតសម្រាប់ចំណីសត្វ", + "SWEET_CORN": "ពោតផ្អែម", + "SWEET_LIME": "ក្រូចឆ្មារផ្អែម", + "SWEET_PEPPER": "ម្ទេសប្លោកផ្អែម", + "SWEET_POTATO": "ដំឡូងឈ្វា", + "SWEET_SORGHUM": "ដើមស៊ើហ្គុមផ្អែម", + "TANGERINE": "ផ្លែក្រូចខ្វិច", + "TANNIA": "មើមត្រាវតានីញ៉ា", + "TAPIOCA_CASSAVA": "ដំឡូងមី​​​​​​​​​តាពីយូកា (ដំឡូងមី)", + "TARO": "ត្រាវ", + "TEA": "តែ", + "TEF": "គ្រាប់ធញ្ញជាតិថេហ្វ", + "TIMOTHY": "ស្មៅទីម៉ូថេ", + "TOBACCO": "ថ្នាំជក់", + "TOMATO": "ផ្លែប៉េងប៉ោះ", + "TREFOIL": "ស្មៅត្រីហ្វូយ", + "TRITICALE_FOR_FODDER": "ស្រូវទ្រីទីកាលីសម្រាប់ចំណីសត្វ", + "TUNG_TREE": "ដើមធុង", + "TURNIP": "មើមស្ពៃ", + "TURNIP_EDIBLE": "មើមស្ពៃសម្រាប់បរិភោគ", + "TURNIP_FOR_FODDER": "មើមស្ពៃសម្រាប់ចំណីសត្វ", + "URENA_CONGO_JUTE": "ដើមយូរ់េណា (ក្រចៅកុងហ្គោ)", + "VANILLA": "វ៉ានីឡា", + "VETCH_FOR_GRAIN": "សណ្តែកវ៉ិតឆ៍សម្រាប់យកគ្រាប់", + "WALNUT": "គ្រាប់វ៉ាល់ណាត់", + "WATERMELON": "ផ្លែឪឡឹក", + "WHEAT": "ស្រូវសាលី", + "YAM": "ដំឡូងឈាមមាន់", + "YERBA_MATE": "តែយ៉ឺបាម៉ាតេ", + "ABIU": "ផ្លែអាប៊ីយូ", + "ACAI_PALM": "ដើមត្នោតអាសៃ", + "ACHACHA": "ផ្លែអាឆាឆា", + "ALFALFA_SPROUTS": "កូនពន្លកស្មៅអាល់ហ្វាល់ហ្វា", + "ALLSPICE": "គ្រឿងទេសអលស្ពៃស៍", + "ALOE_VERA": "ប្រទាលកន្ទុយក្រពើ", + "AMARANTH": "ធញ្ញជាតិអាម៉ារ៉ានថ៍", + "ANGICO_VERMELHO": "ដើមអង់ហ្សីកូពណ៌ក្រហម", + "APPLE_BANANA": "ចេកណាំវ៉ាប្រភេទម្យ៉ាង", + "APPLE_MALAY_MALAY_APPLE": "ផ្លែជម្ពូ (ប៉ោមម៉ាឡេ)", + "ARAZA_FRUIT": "ផ្លែអារ៉ាហ្សា", + "ARRACACHA": "មើមអារ៉ាកាឆា", + "ARUGULA": "បន្លែអារ៉ូហ្គូឡា", + "BAMBOO_COMMON": "ដើមឫស្សីទូទៅ", + "BANANA_PASSIONFRUIT": "ផ្លែម៉ាឡាក់កាវែង", + "BASIL": "ជីរនាងវង", + "BEET_TABLE_RED": "មើមប៊ីតក្រហមហូបស៊ុប", + "BELL_PEPPER": "ម្ទេសប្លោក", + "BERGAMOT_ORANGE": "ក្រូចសើចបារាំងប៊ឺហ្គាម៉ត", + "BIG_LEAF_MAHOGANY_MOGNO_BRASILEIRO": "ដើមម៉ាហូហ្គានីស្លឹកធំ (ឈើគ្រញូងប្រេស៊ីល)", + "BILIMBI": "ផ្លែទ្រលឹងតឹង", + "BLACK_OATS": "ស្រូវអូតខ្មៅ", + "BRAZILIAN_GRAPE_TREE": "ដើមទំពាំងបាយជូរប្រេស៊ីល", + "BRAZILWOOD_TREE": "ដើមឈើប្រេស៊ីល", + "BROWN_SALWOOD_ACÁCIA_MANGIUM": "ដើមអាកាស៊ា (អាជាតិយ៉ាម៉ង់ហ្គីម)", + "BURITI_PALM_BURITI": "ដើមត្នោត(ប៊ូរីទី)", + "BUTTERFLY_PEA": "ផ្កាអញ្ច័ន", + "CALENDULA": "ផ្កាស្បៃរឿងអឺរ៉ុប", + "CAPE_GOOSEBERRY": "ផ្លែកេបហ្គូសប៊ឺរី", + "CEGA_MACHADO": "ដើមឈើកេហ្គាម៉ាឆាដូ", + "CHARD": "ស្ពៃឆាត", + "CHERRY_BARBADOS_BARBADOS_CHERRY": "ផ្លែឈឺរី (បាបាដូស)", + "CHERRY_SURINAM_SURINAM_CHERRY": "ផ្លែឈឺរី (ស៊ូរីណាម)", + "CHIA": "គ្រាប់ជីអឺរ៉ុប", + "CHICHÁ_DO_CERRADO": "ដើមឈីឆាដូសេរ៉ាដូ", + "CHIVE": "គូឆាយបារាំង", + "CHUPA_CHUPA": "ផ្លែឈូប៉ាឈូប៉ា", + "CILANTRO": "ស្លឹកវ៉ាន់ស៊ុយ", + "COCHINEAL_CACTUS_PALMA_NOPAL": "ដើមដំបងយក្ស(ណូប៉ាល់)", + "COCOYAM_NEW_COCOYAM_XANTHOSOMA_SPP": "ដំឡូងត្រាវ (កូកូយ៉ាំថ្មី) (ដំឡូងសានតូសូម៉ា)", + "COLA_NUT": "គ្រាប់កូឡា", + "COLLARDS": "ស្ពៃកាត់ស្លឹកបៃតងខូឡាដ", + "COPAÍBA": "ដើមជ័រប្រេងកូប៉ៃបា", + "CORIANDER_LONG_LONG_CORIANDER": "ជីរបន្លា​ (ជីរណាវែង)", + "CORN_SALAD": "បន្លែសាឡាត់ខន", + "CUPUAÇU": "ផ្លែគូពូអាស៊ូ", + "DAIKON_RADISH_NABO_FORRAJERO_FORAGE": "មើមឆាយថាវដៃកុន ​(ស្ពៃរ៉ាឌីសជប៉ុន សម្រាប់ចំណីសត្វ)", + "DRAGONFRUIT": "ផ្លែស្រកានាគ", + "EDDO_EDDOE": "មើមត្រាវតូច (អេដូ)", + "EPAZOTE": "ជីរអេប៉ាហ្សូត", + "ESPINHEIRA_SANTA": "រុក្ខជាតិឱសថអែសពីណីរ៉ាសានតា", + "ETHIOPIAN_NIGHTSHADE": "ត្រប់អេត្យូពី", + "GENIPAP_TREE": "ដើមហ្សេនីប៉ាប់", + "GERANIUM_SPP": "ផ្កាហ្សេរ៉ានីញ៉ូមអំបូរផ្សេងៗច្រើនប្រភេទ។", + "GINGKO_BILOBA": "ស្លឹកផ្កាជីងកូ", + "GOOSEBERRY_BARBADOS_BARBADOS_GOOSEBERRY": "ផ្លែហ្គូសប៊ឺរីបាបាដូស​ (ផ្លែប៉េងបោះស្រោម)", + "GROUNDCHERRY": "ផ្លែទំពាំងបាយជូរក្នុងស្រោម", + "GUACO": "វល្លិហ្គូអាគូ", + "GUARANÁ": "ផ្លែហ្គារ៉ាណា", + "GUEROBA": "ដើមត្នោតហ្គីរ៉ូបា", + "HEMP_SUNN_CROTALARIA": "ដើមសណ្តែកជួរ (ក្រូតាម៉ារីយ៉ា)", + "HENNA": "ដើមល័ក្ខហែនណា", + "ICE_CREAM_BEAN": "ផ្លែសណ្តែកទឹកកក", + "IMBURANA_DE_CHEIRO_CUMARU_NORDESTINO": "ដើមអ៊ីមប៊ូរ៉ាណា", + "INCA_PEANUT": "សណ្តែកដីអ៊ីនកា", + "JACK_BEAN": "សណ្តែកដាវ", + "JACKFRUIT": "ផ្លែខ្នុរ", + "JATOBÁ_DO_CERRADO": "ដើមហ្សាតូបាសេរ៉ាដូ", + "JÍCAMA": "ដំឡូងរលួស", + "JOINTED_FLATSEDGE": "ស្មៅព្រៃមួយប្រភេទ", + "LAMB_S_EAR": "រុក្ខជាតិស្លឹកត្រចៀកចៀម", + "LAUREL": "ស្លឹកឈើក្រអូបការី", + "LEMON_BALM": "ជីរក្រអូបក្លិនក្រូចឆ្មារ", + "LEMON_SCENTED_GUM_EUCALIPTO_CHEIROSO": "ដើមប្រេងខ្យល់ក្លិនក្រូចឆ្មារ (ដើមប្រេងខ្យល់)", + "LIPSTICK_TREE": "ដើមល័ក្ខលាបបបូរមាត់", + "LUPIN_LUPINO": "គ្រាប់សណ្តែក​ (លូភីន)", + "MACAW_PALM_MACAÚBA": "ដើមត្នោត (ម៉ាកាអ៊ូបា)", + "MAIZE_FOR_SILAGE": "ពោតសម្រាប់ធ្វើចំណីផ្អាប់សត្វ", + "MANGOSTEEN": "ផ្លែមង្ឃុត", + "MANGOSTEEN_FALSE_FALSE_MANGOSTEEN": "ផ្លែមង្ឃុតព្រៃ (មង្ឃុតក្លែងក្លាយ)", + "MARANG": "ផ្លែម៉ារ៉ាំង", + "MARCELA": "ផ្កាម៉ាសេឡា", + "MARJORAM": "ស្លឹកម៉ាចូរ៉ាំ", + "MIGNONETTE_VINE": "វល្លិផ្កាកន្ទុយឆ្កែស", + "MIRACLE_FRUIT": "ផ្លែប្តូររសជាតិ", + "MOCAMBO_TREE": "ដើមមូកាំបូ", + "MOMBIN_PURPLE_PURPLE_MOMBIN_OR_SPANISH_PLUM": "ផ្លែម៉ំប៊ីនពណ៌ស្វាយ (ផ្លែព្រឿងអេស្ប៉ាញ)", + "MOMBIN_YELLOW_YELLOW_MOMBIN": "ផ្លែម៉ប៊ីនលឿង​ ​(ផ្លែម៉ប៊ីនលឿង)", + "MOMOQUI_SIBIPIRUNA": "ដើមម៉ូម៉ូគី (ស៊ីប៊ីពីវីណា)", + "MONKEY_PEPPER_PIMENTA_DE_MACACO": "ម្រេចស្វា (ភីម៉ង់តាដឺម៉ាកាកូ)", + "MULBERRY_INDIAN_INDIAN_MULBERRY": "ដើមផ្លែមនឥណ្ឌា (មនឥណ្ឌា)", + "MULUNGU": "ដើមមូលុងហ្គូ", + "OCA": "មើមអូកា", + "ONION_RED": "ខ្ទឹមបារាំងក្រហម", + "ONION_WELSH_WELSH_ONION": "ដើមខ្ទឹមជប៉ុន​ (ខ្ទឹមម្យ៉ាង)", + "OPPOSITELEAF_RUSSIAN_THISTLE": "ដើមអូប៉ូស៊ីតលីហ្វ រ៉ុស្ស៊ីនធីសល៍", + "OREGANO": "ស្លឹកអូរីហ្គាណូ", + "PALM_BAHIA_PIASSABA_BAHIA_PIASSABA_PALM": "ដើមត្នោតបាហ៊ីយ៉ាពីអាសាបា​​ (ត្នោតបាហ៊ីយ៉ាពីអាសាបា)", + "PALM_JUSSARA_JUSSARA_PALM": "ដើមត្នោតហ្សូសារ៉ា​ (ត្នោតហ្សូសារ៉ា)", + "PALM_PEACH_PEACH_PALM": "ដើមត្នោតផីច (ដើមត្នោតមានផ្លែដែលអាចបរិភោគបាន ស្រដៀងផ្លែប៉េស)", + "PALM_SAGO_METROXYLON_SAGU": "ដើមត្នោតសាវូ (មេត្រូស៊ីឡុន សាវូ)", + "PARSLEY": "វ៉ាន់ស៊ុយប៉ាស្លី", + "PASSIONFRUIT": "ផ្លែផាសិន", + "PENNYROYAL": "ជីរផេននីរ៉ូយ៉ាល់", + "PEPPER_BRAZILIAN_BRAZILIAN_PEPPER": "ដើមម្រេច​ (ប្រេស៊ីល)", + "PLUM_JAVA_JAVA_PALM": "ផ្លែព្រូនជ្វា (ព្រូនជ្វា)", + "PLUM_JUNE_JUNE_PALM": "ផ្លែម្កាក់ (ម្កាក់)", + "PURSLANE": "ស្មៅពួស្លេន/ផ្កា​ម៉ោង​ប្រាំបី", + "PYRETHRUM": "ផ្កាផាយរ៉េត្រម", + "QUICKSTICK": "ដើមអង្កាញ់ឃ្វីកស្ទិក", + "RAMBUTAN": "ផ្លែសៅម៉ៅ", + "RHEA_RAMIE": "ដើមរ៉ាមី", + "ROCOTO_PEPPER": "ម្ទេសរ៉ូកូតូ", + "ROSE_APPLE": "ផ្លែជម្ពូ", + "ROSE_GUM_EUCALYPTUS_EUCALIPTO_GRANDIS": "ដើមប្រេងខ្យល់ផ្កាឈូក (អឺកាលីបតូស ហ្គ្រង់ឌីស)", + "ROSELLE": "ផ្កាក្រហមរ៉ូសែល", + "ROSEMARY": "ស្លឹករ៉ូស្មែរី", + "SABA_NUT_CASTANHA_DO_MARANHÃO": "គ្រាប់សាបា (គ្រាប់ម៉ារ៉ាញ៉ៅ)", + "SAFFRON": "ផ្កាសាហ្វរ៉ុន", + "SANGRA_D_AGUA": "ដើមឈើសង់ហ្គ្រាដាក្វា", + "SATSUMA_MANDERINE_TANGERINE": "ក្រូចសាតស៊ូម៉ា​(ក្រូចម៉ាន់ដារីន/ក្រូចតេនជេរីន)", + "SCHOTT_MANGARITO": "មើមម៉ង់ហ្គារីតូ (អំបូរត្រាវ)", + "SESSILE_JOYWEED": "បន្លែត្រកួនព្រៃផ្កាស", + "SHEA_TREE": "ដើមស៊ា", + "SOAPBERRY_SABONETEIRA": "ដើមសាប៊ូ (សាបូណេតេរ៉ា)", + "SORREL": "ម្ជូរបារាំង/សណ្តាន់", + "SOURSOP": "ផ្លែទៀបបារាំង", + "SOUTHERN_BLUE_GUM_EUCALIPTO_GLÓBULUS": "ដើមប្រេងខ្យល់ខៀវភាគខាងត្បូង​(ដើមអ៊ុកាលីបតុសគ្លូប៊ូលុស)", + "SPELT": "ស្រូវសាលីស្ពែលថ៍", + "ST_JOHN_S_WORT": "ផ្កាសេនចនវ៉ត", + "STARFRUIT": "ផ្លែស្ពឺ", + "STEVIA": "ស្មៅផ្អែមស្តេវីយ៉ា", + "STRAWBERRY_GUAVA": "ផ្លែត្របែក ស្ត្រប៊ឺរី", + "TAHITIAN_GOOSEBERRY_TREE": "ដើមកន្ទួត", + "THYME": "ស្លឹកថាម", + "TIMOTHY_GRASS": "ស្មៅទីម៉ូថេ", + "TINGUI": "ដើមទីនហ្គី", + "TREE_SPINACH": "ដើមស្ពៃពួយឡេងយក្ស", + "TRITICALE": "ស្រូវទ្រីទីកាលី", + "TROPICAL_ALMOND_TREE_AMENDOEIRA_DA_PRAIA_SETE_COPAS": "ដើមអាល់ម៉ុនត្រូពិច (អាម៉េនដូអេរ៉ា ដា ប្រាយា / សេតេ កូបាស)", + "TURMERIC": "រមៀត", + "UVAIA": "ផ្លែអ៊ូវ៉ៃយ៉ា", + "VELVET_BEAN": "សណ្តែកវល្លិវ៉ែលវិត", + "WEST_INDIAN_GHERKIN": "ត្រសក់ឥណ្ឌាម្យ៉ាង", + "WEST_INDIAN_LOCUST_JATOBÁ_DA_MATA": "ដើមឡុកស្ត៍វេសឥណ្ឌា​ (ចាតូបាដាម៉ាតា)", + "YACON": "មើមដំឡូងយ៉ាកុន", + "ZUCCHINI": "ផ្លែហ្សូគីនី" +} diff --git a/packages/webapp/public/locales/km/crop_group.json b/packages/webapp/public/locales/km/crop_group.json new file mode 100644 index 0000000000..b4f031c167 --- /dev/null +++ b/packages/webapp/public/locales/km/crop_group.json @@ -0,0 +1,13 @@ +{ + "BEVERAGE_AND_SPICE_CROPS": "ដំណាំភេសជ្ជៈ និងគ្រឿងទេស", + "CEREALS": "ដំណាំធញ្ញជាតិ", + "FRUITS_AND_NUTS": "ផ្លែឈើ និងគ្រាប់ធញ្ញជាតិ", + "HIGH_STARCH_ROOT_TUBER_CROP": "ដំណាំរឹស និងមើមដែលមានម្សៅខ្ពស់", + "LEGUMINOUS_CROPS": "ដំណាំពពួកសណ្តែក", + "OILSEED_CROPS": "ដំណាំគ្រាប់ប្រេង", + "OTHER_CROPS": "ដំណាំផ្សេង‌ៗ", + "POTATOES_AND_YAMS": "ដំឡូងបារាំង និងដំឡូងជ្វា", + "STIMULANT_SPICE_AROMATIC_CROPS": "ដំណាំជំរុញ ដំណាំគ្រឿងទេស និងដំណាំក្លិនក្រអូប", + "SUGAR_CROPS": "ដំណាំស្ករ", + "VEGETABLE_AND_MELONS": "បន្លែ និងផ្លែត្រសក់ផ្អែមមីឡុង" +} diff --git a/packages/webapp/public/locales/km/crop_nutrients.json b/packages/webapp/public/locales/km/crop_nutrients.json new file mode 100644 index 0000000000..c440178bfb --- /dev/null +++ b/packages/webapp/public/locales/km/crop_nutrients.json @@ -0,0 +1,28 @@ +{ + "INIT_KC": "មេគុណទឹករបស់ដំណាំនៅដំណាក់កាលដំបូង", + "MID_KC": "មេគុណទឹករបស់ដំណាំនៅដំណាក់កាលកណ្តាល", + "END_KC": "មេគុណទឹករបស់ដំណាំដំណាក់កាលចុងក្រោយនៃការលូតលាស់", + "MAX_HEIGHT": "កម្ពស់អតិបរមា", + "PROTEIN": "ប្រូតេអ៊ីន", + "LIPID": "លីពីត / ខ្លាញ់", + "ENERGY": "ថាមពល", + "CALCIUM": "កាល់ស្យូម", + "IRON": "ដែក", + "MAGNESIUM": "ម៉ាញ៉េស្យូម", + "PH": "កម្រិតអាស៊ីត-អាល់កាលី/pH", + "K": "ប៉ូតាស្យូម", + "NA": "សូដ្យូម", + "ZINC": "ស័ង្កសី", + "COPPER": "ទង់ដែង", + "MANGANESE": "ម៉ង់ហ្គាណេស", + "VITA_RAE": "វីតាមីនអា", + "VITAMIN_C": "វីតាមីនសេ", + "THIAMIN": "វីតាមីនបេ​​​​មួយ", + "RIBOFLAVIN": "វីតាមីនបេ​​​ពីរ", + "NIACIN": "វីតាមីនបេ​​​បី", + "VITAMIN_B6": "វីតាមីនបេ​​​ ប្រាំមួយ", + "FOLATE": "វីតាមីនបេ ប្រាំបួនឬ ហ្វូលេត", + "VITAMIN_B12": "វីតាមីនបេ​​​ដប់ពីរ​", + "MAX_ROOTING": "ជំរៅរឹសអតិបរមា", + "NUTRIENT_CREDITS": "ឥណទានសារធាតុចិញ្ចឹម / បរិមាណសារធាតុចិញ្ចឹមដែលមានស្រាប់" +} \ No newline at end of file diff --git a/packages/webapp/public/locales/km/expense.json b/packages/webapp/public/locales/km/expense.json new file mode 100644 index 0000000000..a8ff0cc56b --- /dev/null +++ b/packages/webapp/public/locales/km/expense.json @@ -0,0 +1,54 @@ +{ + "EQUIPMENT": { + "EXPENSE_NAME": "ឧបករណ៍", + "CUSTOM_DESCRIPTION": "ចំណាយទាក់ទងនឹងឧបករណ៍សាមញ្ញ សម្ភារៈ និងផ្នែកសម្រាប់ដំណើរការកសិដ្ឋាន។" + }, + "SOIL_AMENDMENT": { + "EXPENSE_NAME": "កែលម្អដី", + "CUSTOM_DESCRIPTION": "ចំណាយទាក់ទងនឹងសារធាតុបន្ថែមដូចជា ជី ដែលធ្វើឲ្យគុណភាពដីប្រសើរឡើង។" + }, + "MACHINERY": { + "EXPENSE_NAME": "ម៉ាសុីន", + "CUSTOM_DESCRIPTION": "ចំណាយទាក់ទងនឹងការទិញ ការជួលរយៈពេលវែង ការជួលប្រើ និងការថែទាំគ្រឿងម៉ាស៊ីន។" + }, + "PEST_CONTROL": { + "EXPENSE_NAME": "ត្រួតពិនិត្យថ្នាំសត្វល្អិត", + "CUSTOM_DESCRIPTION": "ចំណាយទាក់ទងនឹងការទិញសារធាតុ ផលិតផល និងឧបករណ៍សម្រាប់គ្រប់គ្រងសត្វល្អិត ឬ​ប្រភេទសារពាង្គកាយមិនចង់បាន។" + }, + "FUEL": { + "EXPENSE_NAME": "ប្រេងឥន្ធនៈ", + "CUSTOM_DESCRIPTION": "ចំណាយទាក់ទងនឹងការប្រើប្រាស់ប្រេងឥន្ធនៈសម្រាប់ហេដ្ឋារចនាសម្ព័ន្ធ យានយន្ត គ្រឿងម៉ាស៊ីន និងឧបករណ៍។" + }, + "LAND": { + "EXPENSE_NAME": "ដី", + "CUSTOM_DESCRIPTION": "ចំណាយទាក់ទងនឹងការទិញ ការហិរញ្ញប្បទាន ការជួល ការប្រើប្រាស់ ថ្លៃពន្ធ និងថ្លៃផ្សេងៗ សម្រាប់កម្មសិទ្ធិ ឬការប្រើប្រាស់ដី។" + }, + "SEEDS_AND_PLANTS": { + "EXPENSE_NAME": "គ្រាប់ពូជ និងរុក្ខជាតិ", + "CUSTOM_DESCRIPTION": "ការទិញគ្រាប់ពូជ សំណាប និងកូនរុក្ខជាតិសម្រាប់ដាំ និងស្ទូង។" + }, + "MISCELLANEOUS": { + "EXPENSE_NAME": "ផ្សេងៗ", + "CUSTOM_DESCRIPTION": "អ្វីផ្សេងទៀតទាំងអស់។ ពិចារណាបង្កើតប្រភេទចំណាយផ្ទាល់ខ្លួន ប្រសិនបើអ្នកមានចំណាយបន្ថែមដូចនេះនៅពេលអនាគត។" + }, + "UTILITIES": { + "EXPENSE_NAME": "សេវាផ្គត់ផ្គង់មូលដ្ឋាន", + "CUSTOM_DESCRIPTION": "ចំណាយជាប្រចាំទាក់ទងនឹងអគ្គិសនី ឧស្ម័ន ទឹក (រួមទាំងការស្រោចស្រព) ការប្រមូលសំរាម និងសេវាផ្សេងៗតាមកាលកំណត់។" + }, + "LABOUR": { + "EXPENSE_NAME": "ពលកម្មតាមកិច្ចសន្យា", + "CUSTOM_DESCRIPTION": "ចំណាយដែលពាក់ព័ន្ធនឹងការជួលបុគ្គលិក ឬកម្មករតាមកិច្ចសន្យា។" + }, + "INFRASTRUCTURE": { + "EXPENSE_NAME": "ហេដ្ឋារចនាសម្ព័ន្ធ", + "CUSTOM_DESCRIPTION": "ចំណាយដែលពាក់ព័ន្ធនឹងការសាងសង់ ឬកែលម្អអគារ និងសំណង់ផ្សេងៗនៅក្នុងកសិដ្ឋាន។" + }, + "TRANSPORTATION": { + "EXPENSE_NAME": "ការដឹកជញ្ជូន", + "CUSTOM_DESCRIPTION": "ចំណាយដែលពាក់ព័ន្ធនឹងការដឹកជញ្ជូនធាតុចូល ផលិតផល និងមនុស្ស។" + }, + "SERVICES": { + "EXPENSE_NAME": "សេវាកម្ម", + "CUSTOM_DESCRIPTION": "ចំណាយដែលពាក់ព័ន្ធនឹងសេវាកម្មផ្សេងៗ ដូចជា ការទទួលអាជ្ញាប័ណ្ណ វិញ្ញាបនបត្រ ការគាំទ្រផ្នែកក្សេត្រសាស្ត្រ ការធ្វើតេស្ត ការធ្វើទីផ្សារ និងសេវាកម្មផ្សេងទៀត។" + } +} diff --git a/packages/webapp/public/locales/km/fertilizer.json b/packages/webapp/public/locales/km/fertilizer.json new file mode 100644 index 0000000000..5308f87fd4 --- /dev/null +++ b/packages/webapp/public/locales/km/fertilizer.json @@ -0,0 +1,28 @@ +{ + "COMPOST_MANURE": "ជីកំប៉ុស្ត (លាមកសត្វ)", + "COMPOST_HIP": "ជីកំប៉ុស្ត​ ​​​​​​​​​​​​​​(HIP)", + "BEEF-FEEDLOT-_SOLID_DRY": "លាមកគោចិញ្ចឹមយកសាច់រឹង ​(ស្ងួត)​​​​​​", + "BEEF-FEEDLOT-_SOLID_MOIST": "លាមកគោចិញ្ចឹមយកសាច់រឹង ​(សេីម)​​​​​​", + "BEEF-_LIQUID": "លាមករាវពីគោសាច់", + "CHICKEN-BROILER_GENERAL": "មាន់សាច់ (ទូទៅ)", + "CHICKEN-BROILER_MANURE_AGED_OUTDOORS": "មាន់សាច់ (លាមកចាស់នៅខាងក្រៅ)", + "CHICKEN-BROILER_MANURE_FRESH_FROM_BARN": "មាន់សាច់ (លាមកថ្មីពីរោងចិញ្ចឹម)", + "CHICKEN-BROILER_BREEDER": "មាន់បង្កាត់ពូជមាន់សាច់", + "CHICKEN-LAYER": "មាន់យកពង", + "DAIRY-_SOLID_DRY": "លាមកគោយកទឹកដោះរឹង​ ​(ស្ងួត)", + "DAIRY-_SOLID_MOIST": "លាមកគោយកទឹកដោះរឹង​ ​(សេីម)", + "DAIRY-_LIQUID_THICK_SLURRY": "លាមកគោយកទឹកដោះរាវ​ ​(ជាល្បាយខាប់)", + "DAIRY-_LIQUID_MEDIUM_SLURRY": "លាមកគោយកទឹកដោះរាវ​ ​(ជាល្បាយមិនខាប់មិនរាវ)", + "DAIRY-_LIQUID_QUITE_WATERY": "លាមកគោយកទឹកដោះរាវ​ ​(ជាលក្ខណៈរាវ)", + "DAIRY-_LIQUID_VERY_WATERY": "លាមកគោយកទឹកដោះរាវ​ ​(ជាលក្ខណៈរាវខ្លាំង)", + "GOAT_DAIRY": "ពពែ​ ​(ទឹកដោះ)", + "HOG-_LIQUID": "លាមកជ្រូករាវ", + "HOG-_SOLID": "លាមកជ្រូករឹង", + "HORSE": "សេះ", + "MINK": "សត្វម៉្យាងដែលស្រដៀងសំពោច", + "SHEEP": "ចៀម", + "TURKEY_MANURE_AGED_>7_WEEKS_OUT_OF_BARN": "មាន់ទួរគី (លាមកចាស់លើសពី 7 សប្តាហ៍នៅក្រៅបន្ទប់ចិញ្ចឹម)", + "TURKEY_MANURE_FRESH_FROM_BARN_<7_WEEKS": "មាន់ទួរគី (លាមកថ្មីតិចជាង 7 សប្តាហ៍)", + "BIOSOLIDS-_ANAEROBICALLY_DIGESTED_&_DEWATERED": "សំណល់សរីរាង្គពីប្រព័ន្ធទឹកកខ្វក់ ដែលបានរំលាយដោយគ្មានអុកស៊ីសែន និងបានបញ្ចេញទឹកចេញ", + "OTHER": "ផ្សេងទៀត" +} diff --git a/packages/webapp/public/locales/km/filter.json b/packages/webapp/public/locales/km/filter.json new file mode 100644 index 0000000000..44c599628d --- /dev/null +++ b/packages/webapp/public/locales/km/filter.json @@ -0,0 +1,50 @@ +{ + "CROP_CATALOGUE": { + "ABANDONED": "បោះបង់", + "ACTIVE": "សកម្ម", + "COMPLETE": "បំពេញ", + "LOCATION": "ទីតាំង", + "NEEDS_PLAN": "ត្រូវការផែនការ", + "PLANNED": "មានផែនការ", + "STATUS": "ស្ថានភាព", + "SUPPLIERS": "អ្នកផ្គត់ផ្គង់" + }, + "DOCUMENTS": { + "CLEANING_PRODUCT": "ផលិតផលសម្រាប់សម្អាត", + "CROP_COMPLIANCE": "ការអនុវត្តតាមស្តង់ដារដំណាំ", + "FERTILIZING_PRODUCT": "ផលិតផលជី", + "INVOICES": "វិក័យបត្រ", + "OTHER": "ផ្សេងទៀត", + "PEST_CONTROL_PRODUCT": "ផលិតផលត្រួតពិនិត្យថ្នាំសត្វល្អិត", + "RECEIPTS": "បង្កាន់ដៃ", + "SOIL_AMENDMENT": "ការកែប្រែដី", + "SOIL_SAMPLE_RESULTS": "លទ្ធផលសំណាកដី", + "UNCATEGORIZED": "មិនទាន់ចាត់ប្រភេទ", + "WATER_SAMPLE_RESULTS": "លទ្ធផលសំណាកទឹក" + }, + "FILTER": { + "FROM_DATE": "ពី", + "TO_DATE": "ទៅ", + "VALID_ON": "មានសុពលភាពដល់" + }, + "INVENTORY": { + "CUSTOM": "បង្កើតតាមតម្រូវការ", + "CUSTOM_OR_LITEFARM_LIBRARY": "បណ្ណាល័យ ឡៃហ្វាម រឺ​​ បណ្ណាល័យបង្កើតតាមតម្រូវការ", + "DRY": "ស្ងួត", + "FERTILISER_TYPE": "ប្រភេទជី", + "LIQUID": "រាវ", + "LITEFARM_LIBRARY": "បណ្ណាល័យ ឡៃហ្វាម", + "TITLE": "តម្រងជ្រើសតែផលិតផលកែដី" + }, + "TASKS": { + "ABANDONED": "បោះបង់", + "ACTIVE": "សកម្ម", + "COMPLETED": "បំពេញ", + "FOR_REVIEW": "សម្រាប់ពិនិត្យ", + "LATE": "យឺត", + "LOCATION": "ទីតាំង", + "PLANNED": "មានផែនការ", + "STATUS": "ស្ថានភាព", + "SUPPLIERS": "អ្នកផ្គត់ផ្គង់" + } +} diff --git a/packages/webapp/public/locales/km/gender.json b/packages/webapp/public/locales/km/gender.json new file mode 100644 index 0000000000..f1a233d6c6 --- /dev/null +++ b/packages/webapp/public/locales/km/gender.json @@ -0,0 +1,6 @@ +{ + "FEMALE": "ស្រី", + "MALE": "ប្រុស", + "OTHER": "ផ្សេងទៀត", + "PREFER_NOT_TO_SAY": "មិនចង់បញ្ជាក់" +} diff --git a/packages/webapp/public/locales/km/harvest_uses.json b/packages/webapp/public/locales/km/harvest_uses.json new file mode 100644 index 0000000000..3429cd40a2 --- /dev/null +++ b/packages/webapp/public/locales/km/harvest_uses.json @@ -0,0 +1,12 @@ +{ + "SALES": "ការលក់", + "SELF-CONSUMPTION": "ប្រើប្រាស់ក្នុងគ្រួសារ", + "ANIMAL_FEED": "ចំណីសត្វ", + "COMPOST": "ជីកំប៉ុស", + "GIFT": "អំណោយ", + "EXCHANGE": "ការដោះដូរ", + "SAVED_FOR_SEED": "ទុកសម្រាប់ធ្វើពូជ", + "NOT_SURE": "មិនប្រាកដ", + "DONATION": "ការបរិច្ចាគ", + "OTHER": "ផ្សេងទៀត" +} diff --git a/packages/webapp/public/locales/km/market_directory_info.json b/packages/webapp/public/locales/km/market_directory_info.json new file mode 100644 index 0000000000..4b168324f1 --- /dev/null +++ b/packages/webapp/public/locales/km/market_directory_info.json @@ -0,0 +1,14 @@ +{ + "MARKET_PRODUCT_CATEGORY": { + "ALCOHOLIC_BEVERAGE": "ភេសជ្ជៈមានជាតិអាល់កុល", + "BAKERY": "ផលិតផលនំដុត", + "DAIRY_PRODUCT": "ផលិតផលទឹកដោះ", + "EGG": "ស៊ុត", + "FLOWER": "ផ្កា", + "FROZEN": "អាហារបង្កក", + "FRUIT": "ផ្លែឈើ", + "MEAT_PRODUCT": "ផលិតផលសាច់", + "PLANT": "សំណាប និងរុក្ខជាតិដាំក្នុងផើង", + "VEGETABLE": "បន្លែ" + } +} diff --git a/packages/webapp/public/locales/km/message.json b/packages/webapp/public/locales/km/message.json new file mode 100644 index 0000000000..a09c9c416e --- /dev/null +++ b/packages/webapp/public/locales/km/message.json @@ -0,0 +1,330 @@ +{ + "ANIMALS": { + "FAILED_CREATE_ANIMALS": "បរាជ័យក្នុងការបង្កើតសត្វ", + "FAILED_CREATE_BATCHES": "បរាជ័យក្នុងការបង្កើតក្រុម", + "FAILED_REMOVE_ANIMALS": "បរាជ័យក្នុងការលុបសត្វដែលបានជ្រើសរើស", + "FAILED_REMOVE_BATCHES": "បរាជ័យក្នុងការលុបក្រុមដែលបានជ្រើសរើស", + "FAILED_UPDATE_ANIMAL": "បរាជ័យក្នុងការធ្វើបច្ចុប្បន្នភាពសត្វ", + "FAILED_UPDATE_BATCH": "បរាជ័យក្នុងការធ្វើបច្ចុប្បន្នភាពក្រុម", + "SUCCESS_CREATE_ANIMALS": "បានបង្កើតសត្វដោយជោគជ័យ", + "SUCCESS_CREATE_BATCHES": "បានបង្កើតក្រុមដោយជោគជ័យ", + "SUCCESS_REMOVE_ANIMALS": "បានលុបសត្វដែលបានជ្រើសរើសដោយជោគជ័យ", + "SUCCESS_REMOVE_BATCHES": "បានលុបក្រុមដែលបានជ្រើសរើសដោយជោគជ័យ", + "SUCCESS_UPDATE_ANIMAL": "បានធ្វើបច្ចុប្បន្នភាពសត្វដោយជោគជ័យ", + "SUCCESS_UPDATE_BATCH": "បានធ្វើបច្ចុប្បន្នភាពក្រុមដោយជោគជ័យ" + }, + "ASSIGN_TASK": { + "ERROR": "បរាជ័យក្នុងការចាត់តាំងភារកិច្ច", + "SUCCESS": "បានចាត់តាំងភារកិច្ចដោយជោគជ័យ" + }, + "ATTACHMENTS": { + "ERROR": { + "CREATE": "បរាជ័យក្នុងការបង្កើតឯកសារ", + "FAILED_ARCHIVE": "បរាជ័យក្នុងការទុកឯកសារចូលបណ្ណសារ", + "FAILED_UNARCHIVE": "បរាជ័យក្នុងការយកឯកសារចេញពីបណ្ណសារ", + "FAILED_UPLOAD": "បរាជ័យក្នុងការផ្ទុកឯកសារភ្ជាប់ឡើង", + "UPDATE": "បរាជ័យក្នុងការធ្វើបច្ចុប្បន្នភាពឯកសារ" + }, + "SUCCESS": { + "ARCHIVE": "បានទុកឯកសារចូលបណ្ណសារដោយជោគជ័យ", + "CREATE": "បានបង្កើតឯកសារដោយជោគជ័យ", + "UNARCHIVE": "បានយកឯកសារចេញពីបណ្ណសារដោយជោគជ័យ", + "UPDATE": "បានធ្វើបច្ចុប្បន្នភាពឯកសារដោយជោគជ័យ" + } + }, + "CROP_VARIETY": { + "ERROR": { + "ADD": "កំហុស៖ បរាជ័យក្នុងការបន្ថែមប្រភេទពូជទៅក្នុងមូលដ្ឋានទិន្នន័យ", + "ADD_ALREADY_EXISTS": "កំហុស៖ ប្រភេទពូជមានរួចហើយ", + "DELETE": "បរាជ័យក្នុងការលុបប្រភេទពូជដំណាំ", + "UPDATE": "បរាជ័យក្នុងការធ្វើបច្ចុប្បន្នភាពប្រភេទពូជដំណាំ" + }, + "SUCCESS": { + "ADD": "បានរក្សាទុកប្រភេទពូជដោយជោគជ័យ!", + "DELETE": "បានលុបប្រភេទពូជដំណាំ", + "UPDATE": "បានធ្វើបច្ចុប្បន្នភាពប្រភេទពូជដំណាំដោយជោគជ័យ" + } + }, + "EXPENSE": { + "ERROR": { + "ADD": "បរាជ័យក្នុងការបន្ថែមចំណាយថ្មី", + "DELETE": "បរាជ័យក្នុងការលុបចំណាយ", + "EXPENSE_DELETED": "ចំណាយនេះលែងមានទៀតហើយ", + "EXPENSE_TYPE_DELETED": "ប្រភេទចំណាយនេះត្រូវបានលុបរួចហើយ", + "UPDATE": "បរាជ័យក្នុងការធ្វើបច្ចុប្បន្នភាពចំណាយ!" + }, + "SUCCESS": { + "ADD": "បានបន្ថែមចំណាយថ្មីដោយជោគជ័យ!", + "DELETE": "បានលុបចំណាយដោយជោគជ័យ!", + "UPDATE": "បានធ្វើបច្ចុប្បន្នភាពចំណាយដោយជោគជ័យ!" + } + }, + "EXPENSE_TYPE": { + "ERROR": { + "ADD": "បរាជ័យក្នុងការបង្កើតចំណាយផ្ទាល់ខ្លួន", + "DELETE": "បរាជ័យក្នុងការលុបចំណាយផ្ទាល់ខ្លួន", + "UPDATE": "បរាជ័យក្នុងការធ្វើបច្ចុប្បន្នភាពចំណាយផ្ទាល់ខ្លួន" + }, + "SUCCESS": { + "ADD": "បានបង្កើតចំណាយផ្ទាល់ខ្លួនដោយជោគជ័យ", + "DELETE": "បានលុបចោលចំណាយផ្ទាល់ខ្លួនទៅដោយជោគជ័យ", + "UPDATE": "បានធ្វើបច្ចុប្បន្នភាពចំណាយផ្ទាល់ខ្លួនដោយជោគជ័យ" + } + }, + "FARM": { + "ERROR": { + "ADD": "បរាជ័យក្នុងការបន្ថែមកសិដ្ឋាន សូមទាក់ទង ឡៃហ្វាម ដើម្បីទទួលបានជំនួយ", + "FETCH": "បរាជ័យក្នុងការទាញយកទិន្នន័យកសិដ្ឋានពីមូលដ្ឋានទិន្នន័យ", + "UPDATE": "បរាជ័យក្នុងការធ្វើបច្ចុប្បន្នភាពព័ត៌មានកសិដ្ឋាន" + }, + "SUCCESS": { + "UPDATE": "បានធ្វើបច្ចុប្បន្នភាពព័ត៌មានកសិដ្ឋានដោយជោគជ័យ!" + } + }, + "FARM_ADDON": { + "FAILED_DISCONNECT_ADDON": "បរាជ័យក្នុងការផ្តាច់ផ្នែកបន្ថែម", + "IRRIGATION_PRESCRIPTION": { + "FAILED_TO_GET": "មិនអាចទាញយកការណែនាំស្រោចស្របបាន" + }, + "SUCCESS_DISCONNECT_ADDON": "ផ្តាច់ផ្នែកបន្ថែមបានជោគជ័យ" + }, + "FARM_NOTE": { + "ERROR": { + "ADD": "បរាជ័យក្នុងការរក្សាទុកកំណត់ត្រា", + "DELETE": "បរាជ័យក្នុងការលុបកំណត់ត្រា", + "EDIT": "បរាជ័យក្នុងការធ្វើបច្ចុប្បន្មភាពកំណត់ត្រា" + }, + "SUCCESS": { + "ADD": "រក្សាទុកកំណត់ត្រាដោយជោគជ័យ", + "DELETE": "លុបកំណត់ត្រាដោយជោគជ័យ", + "EDIT": "ធ្វើបច្ចុប្បន្មភាពកំណត់ត្រាដោយជោគជ័យ" + }, + "SYNC": { + "ADD": { + "NETWORK_ERROR": "សូមអភ័យទោស ប្រព័ន្ធកំពុងមានបញ្ហាបណ្តោះអាសន្ន។ យើងនឹងព្យាយាមបង្កើតកំណត់ត្រារបស់អ្នកឡើងវិញដោយស្វ័យប្រវត្តិ", + "ONLINE": "កំណត់ត្រាត្រូវបានបង្កើត។ វានឹងបង្ហាញនៅពេលអ្នកតភ្ជាប់អ៊ីនធឺណិតវិញ", + "SUCCESS": "កំណត់ត្រាដែលបានបង្កើតក្រៅបណ្ដាញ ត្រូវបានរក្សាទុកដោយជោគជ័យ" + }, + "DELETE": { + "NETWORK_ERROR": "សូមអភ័យទោស ប្រព័ន្ធកំពុងមានបញ្ហាបណ្តោះអាសន្ន។ យើងនឹងព្យាយាមលុបកំណត់ត្រារបស់អ្នកឡើងវិញដោយស្វ័យប្រវត្តិ", + "ONLINE": "កំណត់ត្រាត្រូវបានលុប។ វានឹងត្រូវរក្សាទុកនៅពេលអ្នកតភ្ជាប់អ៊ីនធឺណិតវិញ", + "SUCCESS": "កំណត់ត្រាដែលបានលុបក្រៅបណ្ដាញ ត្រូវបានរក្សាទុកដោយជោគជ័យ" + }, + "EDIT": { + "NETWORK_ERROR": "សូមអភ័យទោស ប្រព័ន្ធកំពុងមានបញ្ហាបណ្តោះអាសន្ន។ យើងនឹងព្យាយាមធ្វើបច្ចុប្បន្នភាពកំណត់ត្រារបស់អ្នកឡើងវិញដោយស្វ័យប្រវត្តិ", + "ONLINE": "កំណត់ត្រាត្រូវបានកែប្រែ។ វានឹងត្រូវរក្សាទុកនៅពេលអ្នកតភ្ជាប់អ៊ីនធឺណិតវិញ", + "SUCCESS": "កំណត់ត្រាដែលបានកែប្រែក្រៅបណ្ដាញ ត្រូវបានរក្សាទុកដោយជោគជ័យ" + }, + "FAILED": "ការផ្លាស់ប្តូរកំណត់ត្រាមិនបានរក្សាទុកជោគជ័យ", + "NOT_FOUND": "មិនអាចរក្សាទុកកំណត់ត្រាបាន៖ កំណត់ត្រានេះលែងមានទៀតហើយ", + "UNAUTHORIZED": "មិនអាចរក្សាទុកកំណត់ត្រាបាន៖ អ្នកមិនមានសិទ្ធិគ្រប់គ្រាន់" + } + }, + "HELP_REQUEST": { + "ERROR": { + "SEND": "មានបញ្ហាកើតឡើងពេលដាក់ស្នើមតិយោបល់របស់អ្នក។ សូមព្យាយាមម្ដងទៀត។" + } + }, + "LOG_HARVEST": { + "ERROR": { + "ADD_USE_TYPE": "បរាជ័យក្នុងការបន្ថែមប្រភេទការប្រើប្រាស់ការប្រមូលផលផ្ទាល់ខ្លួន", + "AMOUNT_TOTAL": "ចំនួនសរុបមិនស្មើនឹងចំនួនដែលត្រូវបែងចែកទេ" + }, + "SUCCESS": { + "ADD_USE_TYPE": "បានបន្ថែមប្រភេទការប្រើប្រាស់ការប្រមូលផលផ្ទាល់ខ្លួនដោយជោគជ័យ" + } + }, + "LOGIN": { + "ERROR": { + "LOGIN_FAIL": "បរាជ័យក្នុងការចូលប្រើព័ត៌មានអ្នកប្រើប្រាស់" + } + }, + "MANAGEMENT_PLAN": { + "ERROR": { + "ABANDON": "បរាជ័យក្នុងការបោះបង់ផែនការដំណាំ!", + "COMPLETE": "បរាជ័យក្នុងការបញ្ចប់ផែនការដំណាំ!", + "DELETE": "បរាជ័យក្នុងការលុ​បផែនការដំណាំ!", + "POST": "បរាជ័យក្នុងការបន្ថែមផែនការដំណាំ!" + }, + "SUCCESS": { + "ABANDON": "បានបោះបង់ផែនការដំណាំដោយជោគជ័យ!", + "COMPLETE": "បញ្ចប់ផែនការដំណាំដោយជោគជ័យ!", + "DELETE": "លុបផែនការដំណាំដោយជោគជ័យ!", + "POST": "បន្ថែមផែនការដំណាំដោយជោគជ័យ!" + } + }, + "MAP": { + "FAIL_PATCH": "បរាជ័យក្នុងការធ្វើបច្ចុប្បន្នភាព", + "FAIL_POST": "បរាជ័យក្នុងការបន្ថែមថ្មី", + "FAIL_DELETE": "បរាជ័យក្នុងការបញ្ឈប់", + "SUCCESS_DELETE": "បានបញ្ឈប់ដោយជោគជ័យ", + "SUCCESS_PATCH": "បានធ្វើបច្ចុប្បន្នភាពដោយជោគជ័យ", + "SUCCESS_POST": "បានរក្សាទុកដោយជោគជ័យ" + }, + "MARKET_DIRECTORY": { + "ERROR": { + "SAVE": "មិនអាចរក្សាទុកព័ត៌មានបញ្ជីទីផ្សារបាន", + "UPDATE": "មិនអាចធ្វើបច្ចុប្បន្នភាពព័ត៌មានបញ្ជីទីផ្សារបាន" + }, + "SUCCESS": { + "SAVE": "ព័ត៌មានបញ្ជីទីផ្សារត្រូវបានរក្សាទុកដោយជោគជ័យ", + "UPDATE": "ព័ត៌មានបញ្ជីទីផ្សារត្រូវបានធ្វើបច្ចុប្បន្នភាពដោយជោគជ័យ", + "UPDATE_LIVE_DATA": "ព័ត៌មានបញ្ជីទីផ្សារត្រូវបានធ្វើបច្ចុប្បន្នភាពដោយជោគជ័យ។ ទិន្នន័យរបស់អ្នកនឹងត្រូវបានធ្វើបច្ចុប្បន្នភាពក្នុងរយៈពេល 24 ម៉ោង។" + } + }, + "MARKET_DIRECTORY_CONSENT": { + "ERROR": "មិនអាចរក្សាទុកការយល់ព្រមសម្រាប់បញ្ជីទីផ្សារបាន", + "SUCCESS": { + "CONSENT": "ការយល់ព្រមសម្រាប់បញ្ជីទីផ្សារត្រូវបានរក្សាទុកដោយជោគជ័យ", + "PARTNER": "ការយល់ព្រមសម្រាប់បញ្ជីទីផ្សារត្រូវបានរក្សាទុកដោយជោគជ័យ។ ទិន្នន័យរបស់អ្នកនឹងត្រូវបានធ្វើបច្ចុប្បន្នភាពក្នុងរយៈពេល 24 ម៉ោង។" + } + }, + "ORGANIC_CERTIFIER_SURVEY": { + "ERROR": { + "CREATE": "បរាជ័យក្នុងការបង្កើតវិញ្ញាបនបត្រ។", + "UPDATE": "បរាជ័យក្នុងការធ្វើបច្ចុប្បន្នភាពវិញ្ញាបនបត្រ!" + } + }, + "PLAN": { + "ERROR": { + "EDIT": "បរាជ័យក្នុងការធ្វើបច្ចុប្បន្នភាពផែនការដំណាំ" + }, + "SUCCESS": { + "EDIT": "បានធ្វើបច្ចុប្បន្នភាពផែនការដំណាំដោយជោគជ័យ" + } + }, + "PRODUCT": { + "ERROR": { + "CREATE": "បរាជ័យក្នុងការបង្កើតផលិតផល", + "REMOVE": "មិនអាចលុបផលិតផលបាន", + "UPDATE": "បរាជ័យក្នុងការធ្វើបច្ចុប្បន្នភាពផលិតផល" + }, + "SUCCESS": { + "CREATE": "បានបង្កើតផលិតផលដោយជោគជ័យ", + "REMOVE": "ផលិតផលត្រូវបានលុបដោយជោគជ័យ", + "UPDATE": "បានធ្វើបច្ចុប្បន្នភាពផលិតផលដោយជោគជ័យ" + } + }, + "REPEAT_PLAN": { + "ERROR": { + "POST": "បរាជ័យក្នុងការធ្វើផែនការ {{planName}} ម្តងទៀត" + }, + "SUCCESS": { + "POST": "បានធ្វើផែនការ {{planName}} ម្តងទៀតដោយជោគជ័យ" + } + }, + "REVENUE": { + "ERROR": { + "EDIT": "បរាជ័យក្នុងការធ្វើបច្ចុប្បន្នភាពចំណូល", + "REVENUE_TYPE_DELETED": "ប្រភេទចំណូលនេះត្រូវបានលុបរួចហើយ" + }, + "SUCCESS": { + "EDIT": "បានធ្វើបច្ចុប្បន្នភាពចំណូលដោយជោគជ័យ" + } + }, + "REVENUE_TYPE": { + "ERROR": { + "ADD": "បរាជ័យក្នុងការបន្ថែមប្រភេទចំណូល", + "DELETE": "បរាជ័យក្នុងការបញ្ឈប់ប្រភេទចំណូល", + "UPDATE": "បរាជ័យក្នុងការធ្វើបច្ចុប្បន្នភាពប្រភេទចំណូល" + }, + "SUCCESS": { + "ADD": "បានបន្ថែមប្រភេទចំណូលដោយជោគជ័យ", + "DELETE": "បានបញ្ឈប់ប្រភេទចំណូលដោយជោគជ័យ", + "UPDATE": "បានធ្វើបច្ចុប្បន្នភាពប្រភេទចំណូលដោយជោគជ័យ" + } + }, + "SALE": { + "ERROR": { + "ADD": "បរាជ័យក្នុងការបន្ថែមការលក់", + "DELETE": "បរាជ័យក្នុងការលុបការលក់ថ្មី", + "SALE_DELETED": "ការលក់នេះលែងមានទៀតហើយ", + "UPDATE": "បរាជ័យក្នុងការធ្វើបច្ចុប្បន្នភាពការលក់" + }, + "SUCCESS": { + "ADD": "បានបន្ថែមការលក់ដោយជោគជ័យ", + "DELETE": "បានលុបការលក់ដោយជោគជ័យ", + "UPDATE": "បានធ្វើបច្ចុប្បន្នភាពការលក់ដោយជោគជ័យ" + } + }, + "TASK": { + "ABANDON": { + "FAILED": "បរាជ័យក្នុងការបោះបង់ភារកិច្ច", + "SUCCESS": "ជោគជ័យក្នុងការបោះបង់ភារកិច្ច", + "SYNC": { + "ONLINE": "ភារកិច្ចត្រូវបានបោះបង់។ វានឹងត្រូវរក្សាទុកនៅពេលអ្នកតភ្ជាប់អ៊ីនធឺណិតវិញ", + "SUCCESS": "ភារកិច្ចដែលបានបោះបង់ក្រៅបណ្ដាញ ត្រូវបានរក្សាទុកដោយជោគជ័យ" + } + }, + "COMPLETE": { + "FAILED": "បរាជ័យក្នុងការបញ្ចប់ភារកិច្ច", + "SUCCESS": "ជោគជ័យក្នុងការបញ្ចប់ភារកិច្ច", + "SYNC": { + "ONLINE": "ភារកិច្ចត្រូវបានបញ្ចប់។ វានឹងត្រូវរក្សាទុកនៅពេលអ្នកតភ្ជាប់អ៊ីនធឺណិតវិញ", + "SUCCESS": "ភារកិច្ចដែលបានបញ្ចប់ក្រៅបណ្ដាញ ត្រូវបានរក្សាទុកដោយជោគជ័យ" + } + }, + "CREATE": { + "FAILED": "បរាជ័យក្នុងការបង្កើតភារកិច្ច", + "SUCCESS": "ជោគជ័យក្នុងការបង្កើតភារកិច្ច", + "SYNC": { + "NETWORK_ERROR": "សូមអភ័យទោស ប្រព័ន្ធកំពុងមានបញ្ហាបណ្តោះអាសន្ន។ យើងនឹងព្យាយាមបង្កើតភារកិច្ចរបស់អ្នកឡើងវិញដោយស្វ័យប្រវត្តិ", + "ONLINE": "ភារកិច្ចត្រូវបានបង្កើត។ វានឹងបង្ហាញនៅពេលអ្នកតភ្ជាប់អ៊ីនធឺណិតវិញ", + "SUCCESS": "ភារកិច្ចដែលបានបង្កើតក្រៅបណ្ដាញ ត្រូវបានរក្សាទុកដោយជោគជ័យ" + } + }, + "DELETE": { + "SYNC": { + "NETWORK_ERROR": "សូមអភ័យទោស ប្រព័ន្ធកំពុងមានបញ្ហាបណ្តោះអាសន្ន យើងនឹងព្យាយាមលុបភារកិច្ចរបស់អ្នកឡើងវិញដោយស្វ័យប្រវត្តិ", + "ONLINE": "ភារកិច្ចត្រូវបានលុប។ វានឹងត្រូវរក្សាទុកនៅពេលអ្នកតភ្ជាប់អ៊ីនធឺណិតវិញ", + "SUCCESS": "ភារកិច្ចដែលបានលុបក្រៅបណ្ដាញ ត្រូវបានរក្សាទុកដោយជោគជ័យ" + } + }, + "SYNC": { + "FAILED": "ការផ្លាស់ប្តូរភារកិច្ចមិនបានរក្សាទុកជោគជ័យ", + "LOCATION_DELETED": "មិនអាចរក្សាទុកភារកិច្ចបាន៖ ទីតាំងនេះត្រូវបានបិទ/ឈប់ប្រើ", + "NETWORK_ERROR": "សូមអភ័យទោស ប្រព័ន្ធកំពុងមានបញ្ហាបណ្តោះអាសន្ន។ យើងនឹងព្យាយាមឡើងវិញដោយស្វ័យប្រវត្តិ", + "NOT_FOUND": "មិនអាចរក្សាទុកភារកិច្ចបាន៖ ភារកិច្ចនេះលែងមានទៀតហើយ", + "UNAUTHORIZED": "មិនអាចរក្សាទុកភារកិច្ចបាន៖ អ្នកមិនមានសិទ្ធិគ្រប់គ្រាន់" + }, + "UPDATE": { + "FAILED": "បរាជ័យក្នុងការធ្វើបច្ចុប្បន្នភាពភារកិច្ច", + "SUCCESS": "ភារកិច្ចត្រូវបានធ្វើបច្ចុប្បន្នភាពដោយជោគជ័យ", + "SYNC": { + "NETWORK_ERROR": "សូមអភ័យទោស ប្រព័ន្ធកំពុងមានបញ្ហាបណ្តោះអាសន្ន។ យើងនឹងព្យាយាមធ្វើបច្ចុប្បន្នភាពភារកិច្ចរបស់អ្នកឡើងវិញដោយស្វ័យប្រវត្តិ", + "ONLINE": "ភារកិច្ចត្រូវបានធ្វើបច្ចុប្បន្នភាព។ វានឹងត្រូវរក្សាទុកនៅពេលអ្នកតភ្ជាប់អ៊ីនធឺណិតវិញ", + "SUCCESS": "ភារកិច្ចដែលបានធ្វើបច្ចុប្បន្នភាពក្រៅបណ្ដាញ ត្រូវបានរក្សាទុកដោយជោគជ័យ" + } + } + }, + "TASK_TYPE": { + "CREATE": { + "FAILED": "បរាជ័យក្នុងការបង្កើតភារកិច្ចផ្ទាល់ខ្លួន", + "SUCCESS": "ជោគជ័យក្នុងការបង្កើតភារកិច្ចផ្ទាល់ខ្លួន" + }, + "DELETE": { + "FAILED": "បរាជ័យក្នុងការលុបភារកិច្ចផ្ទាល់ខ្លួន", + "SUCCESS": "ជោគជ័យក្នុងការលុបភារកិច្ចផ្ទាល់ខ្លួន" + } + }, + "USER": { + "ERROR": { + "ADD": "បរាជ័យក្នុងការបន្ថែមអ្នកប្រើប្រាស់", + "AGREEMENT": "បរាជ័យក្នុងការធ្វើបច្ចុប្បន្នភាពកិច្ចព្រមព្រៀងអ្នកប្រើប្រាស់", + "EXISTS": "អ្នកប្រើប្រាស់មានរួចហើយក្នុងបណ្តាញ​ឡៃហ្វាម", + "INVITE": "កំហុសក្នុងការបង្កើតគណនីអ្នកប្រើប្រាស់ សូមទាក់ទង ឡៃហ្វាម ដើម្បីទទួលបានជំនួយ។", + "MAX_RESET_EMAILS": "តំណសម្រាប់កំណត់ពាក្យសម្ងាត់ឡើងវិញត្រូវបានផ្ញើទៅអ៊ីមែលរបស់អ្នក សូមពិនិត្យប្រអប់សារចូល និងថតសារឥតបានការ។", + "RESET_PASSWORD": "មានកំហុសក្នុងការផ្ញើអ៊ីមែលសម្រាប់កំណត់ពាក្យសម្ងាត់ឡើងវិញ សូមទាក់ទង ឡៃហ្វាម ដើម្បីទទួលបានជំនួយ។", + "RESTORE": "មានកំហុសកើតឡើងពេលស្តារការចូលប្រើ", + "REVOKE": "មានកំហុសកើតឡើងពេលដកសិទ្ធិចូលប្រើ", + "SIGNUP_UNKNOWN": "បញ្ហាមិនស្គាល់! សូមព្យាយាមម្ដងទៀតនៅពេលក្រោយ។", + "UPDATE": "បរាជ័យក្នុងការធ្វើបច្ចុប្បន្នភាពព័ត៌មានអ្នកប្រើប្រាស់" + }, + "SUCCESS": { + "ADD": "បានបន្ថែមអ្នកប្រើប្រាស់ទៅកសិដ្ឋានដោយជោគជ័យ!", + "RESTORE": "បានស្តារការចូលប្រើរបស់អ្នកប្រើប្រាស់", + "REVOKE": "បានដកសិទ្ធិចូលប្រើរបស់អ្នកប្រើប្រាស់!", + "UPDATE": "បានធ្វើបច្ចុប្បន្នភាពព័ត៌មានអ្នកប្រើប្រាស់ដោយជោគជ័យ!" + } + } +} diff --git a/packages/webapp/public/locales/km/profitability.json b/packages/webapp/public/locales/km/profitability.json new file mode 100644 index 0000000000..94abcba0c1 --- /dev/null +++ b/packages/webapp/public/locales/km/profitability.json @@ -0,0 +1,30 @@ +{ + "CTA_BANNER": { + "CTA": "បន្ថែមកំណត់ត្រាប្រតិបត្តិការ", + "DEFAULT": "បន្ថែមប្រតិបត្តិការចុងក្រោយរបស់អ្នក ដើម្បីទទួលបានការវិភាគដែលមានភាពត្រឹមត្រូវ", + "NO_ATTRIBUTIONS": "កំណត់ប្រតិបត្តិការរបស់អ្នកឱ្យជាប់ទាក់ទងនឹងដំណាំ និងក្រុមសត្វ ដើម្បីបង្ហាញការបែងចែកតាមប្រភេទពូជនីមួយៗ", + "NO_TRANSACTIONS": "ចាប់ផ្តើមកត់ត្រាចំណូល និងចំណាយរបស់អ្នក ដើម្បីតាមដានប្រាក់ចំណេញពីដំណាំ និងសត្វរបស់អ្នក" + }, + "KPI": { + "MARGIN": "ប្រាក់ចំណេញ", + "NO_TREND_TOOLTIP": "បន្ថែមទិន្នន័យបន្ថែមពីឆ្នាំមុន ដើម្បីគណនានិន្នាការ", + "YOY_TOOLTIP": "ប្រៀបធៀបទិន្នន័យដូចគ្នានឹងរយៈពេលដូចគ្នាក្នុងឆ្នាំមុន។", + "YOY_TREND": "ធៀបនឹងឆ្នាំមុន", + "YOY_TREND_SHORT": "ឆ្នាំ/ឆ្នាំ" + }, + "LESS_DATA": "ទិន្នន័យតិច", + "MORE_DATA": "ទិន្នន័យច្រើន", + "NET_PROFIT": "ប្រាក់ចំណេញសុទ្ធ", + "TABLE": { + "ANIMAL": "សត្វ", + "EXPENSE": "ចំណាយ", + "FOOTNOTE": "ការបែងចែកប្រាក់ចំណេញតាមដំណាំ និងសត្វរបស់អ្នក សម្រាប់រយៈពេលដែលបានជ្រើសរើស។", + "NO_ANIMALS": "អ្នកមិនមានសត្វនៅក្នុងបញ្ជីស្តុករបស់អ្នកទេ", + "NO_CROP_VARIETIES": "អ្នកមិនមានប្រភេទពូជដំណាំនៅក្នុងកសិដ្ឋានរបស់អ្នកទេ", + "TYPE_TOTAL": "{{type}} សរុប", + "VARIETY": "ប្រភេទពូជ" + }, + "TOP_EXPENSE_CATEGORIES": "ប្រភេទចំណាយចម្បង", + "TOP_REVENUE_CATEGORIES": "ប្រភេទចំណូលចម្បង", + "WIDGET_TITLE": "ប្រាក់ចំណេញ" +} diff --git a/packages/webapp/public/locales/km/revenue.json b/packages/webapp/public/locales/km/revenue.json new file mode 100644 index 0000000000..98e870f473 --- /dev/null +++ b/packages/webapp/public/locales/km/revenue.json @@ -0,0 +1,10 @@ +{ + "ANIMAL_SALE": { + "REVENUE_NAME": "លក់សត្វ", + "CUSTOM_DESCRIPTION": "ចំណូលដែលបានពីការលក់ផលិតផលសត្វ។" + }, + "CROP_SALE": { + "REVENUE_NAME": "លក់ដំណាំ", + "CUSTOM_DESCRIPTION": "ចំណូលដែលទាក់ទងនឹងការលក់ដំណាំដែលបានប្រមូលផលពីកសិដ្ឋាននេះ។" + } +} diff --git a/packages/webapp/public/locales/km/role.json b/packages/webapp/public/locales/km/role.json new file mode 100644 index 0000000000..8f2b7d4fd0 --- /dev/null +++ b/packages/webapp/public/locales/km/role.json @@ -0,0 +1,7 @@ +{ + "EXTENSION_OFFICER": "មន្រ្តីផ្សព្វផ្សាយ", + "MANAGER": "អ្នកគ្រប់គ្រងកសិដ្ធាន", + "OWNER": "ម្ចាស់កសិដ្ធាន", + "WORKER": "កម្មករកសិដ្ធាន", + "WORKER_WITHOUT_ACCOUNT": "កម្មករគ្មានគណនី" +} diff --git a/packages/webapp/public/locales/km/soil.json b/packages/webapp/public/locales/km/soil.json new file mode 100644 index 0000000000..786b19946a --- /dev/null +++ b/packages/webapp/public/locales/km/soil.json @@ -0,0 +1,14 @@ +{ + "CLAY": "ដីឥដ្ឋ", + "CLAY_LOAM": "ដីល្បាយលាយដីឥដ្ឋ", + "LOAM": "ដីល្បាយ", + "LOAMY_SAND": "ដីខ្សាច់លាយដីល្បាយ", + "SAND": "ដីខ្សាច់", + "SANDY_CLAY": "ដីឥដ្ឋលាយខ្សាច់", + "SANDY_CLAYLOAM": "ដីល្បាយដីឥដ្ឋលាយដីខ្សាច់", + "SANDY_LOAM": "ដីល្បាយលាយដីខ្សាច់", + "SILT": "ល្បាប់", + "SILT_LOAM": "ដីល្បាយលាយល្បាប់", + "SILTY_CLAY": "ដីឥដ្ឋល្បាប់", + "SILTY_CLAYLOAM": "ដីល្បាយឥដ្ឋលាយល្បាប់" +} diff --git a/packages/webapp/public/locales/km/task.json b/packages/webapp/public/locales/km/task.json new file mode 100644 index 0000000000..07547976ad --- /dev/null +++ b/packages/webapp/public/locales/km/task.json @@ -0,0 +1,26 @@ +{ + "BED_PREPARATION_TASK": "ការរៀបចំរង", + "DELIVERY": "ការដឹកជញ្ជួន", + "SALE_TASK": "ការលក់", + "SOCIAL_EVENT": "ព្រឹត្តិការណ៍សង្គម", + "SEEDING": "គ្រាប់", + "FERTILIZING": "ដាក់ជី", + "SCOUTING_TASK": "ចុះពិនិត្យ / សង្កេត", + "HARVEST_TASK": "ប្រមូលផល", + "WEEDING": "ដកស្មៅ", + "WASH_AND_PACK_TASK": "លាងសំអាត​និងវេចខ្ចប់", + "PEST_CONTROL_TASK": "ត្រួតពិនិត្យថ្នាំសត្វល្អិត", + "OTHER_TASK": "ផ្សេងទៀត", + "BREAK_TASK": "សម្រាក", + "SOIL_TASK": "លទ្ធផលសំណាកដី", + "IRRIGATION_TASK": "ការស្រាចស្រព", + "TRANSPORT_TASK": "ការដឹងជញ្ជូន", + "FIELD_WORK_TASK": "ការងារនៅទីវាល", + "PLANT_TASK": "ការដាំ", + "TRANSPLANT_TASK": "ស្ទូង", + "SOCIAL_TASK": "សង្គម", + "CLEANING_TASK": "ស្អាត", + "SOIL_AMENDMENT_TASK": "កែលម្អដី", + "MOVEMENT_TASK": "ចលនា", + "SOIL_SAMPLE_TASK": "សំណាកដី" +} diff --git a/packages/webapp/public/locales/km/translation.json b/packages/webapp/public/locales/km/translation.json new file mode 100644 index 0000000000..8ca5438002 --- /dev/null +++ b/packages/webapp/public/locales/km/translation.json @@ -0,0 +1,2281 @@ +{ + "ADD_ANIMAL": { + "ADD_ANIMALS": "បន្ថែមសត្វ", + "ADD_ANIMALS_TITLE": "បន្ថែមសត្វ", + "ADD_DETAILS_INFO": "បំពេញព័ត៌មានសត្វរបស់អ្នកខាងក្រោម ឬរក្សាទុក ហើយបន្តធ្វើនៅពេលក្រោយ។", + "ADD_TO_INVENTORY": "បន្ថែមសត្វទៅក្នុងបញ្ជីស្តុករបស់អ្នក", + "ANIMAL_BASICS": "ព័ត៌មានមូលដ្ឋានអំពីសត្វ", + "ANIMAL_DETAILS": "ព័ត៌មានលម្អិតអំពីសត្វ", + "ANIMALS_TOTAL_one": "សត្វសរុប {{count}} ក្បាល", + "ANIMALS_TOTAL_other": "សត្វសរុប {{count}} ក្បាល", + "ANIMALS_UNSPECIFIED_one": "មិនបានបញ្ជាក់ {{count}}", + "ANIMALS_UNSPECIFIED_other": "មិនបានបញ្ជាក់ {{count}}", + "BATCH_NAME": "ឈ្មោះក្រុម", + "BATCH_NAME_PLACEHOLDER": "វាយបញ្ចូលឈ្មោះក្រុម", + "BREED": "ពូជ", + "BREED_PLACEHOLDER_DISABLED": "សូមជ្រើសរើសប្រភេទជាមុនសិន", + "CREATE_INDIVIDUAL_PROFILES": "បង្កើតប្រវត្តិរូបសត្វនីមួយៗ", + "CREATE_INDIVIDUAL_PROFILES_TOOLTIP": "ជ្រើសរើសជម្រើសនេះ ប្រសិនបើអ្នកចង់តាមដាន និងគ្រប់គ្រងសត្វនីមួយៗដោយឡែក", + "EDIT_BASIC_INFO": "កែសម្រួលព័ត៌មានមូលដ្ឋាន", + "GENERAL_DETAILS": "ព័ត៌មានលម្អិតទូទៅ", + "GENERAL_DETAILS_BATCH": "ព័ត៌មានលម្អិតទូទៅជាក្រុម", + "GROUP_NAME": "ឈ្មោះក្រុម", + "GROUP_NAME_PLACEHOLDER": "វាយបញ្ចូលឈ្មោះក្រុម", + "ORIGIN": "ប្រភពដើម", + "ORIGIN_BATCH": "ប្រភពដើមជាក្រុម", + "OTHER_DETAILS": "ព័ត៌មានផ្សេងទៀត", + "OTHER_DETAILS_BATCH": "ព័ត៌មានបន្ថែមអំពីក្រុម", + "OUT_OF_COUNT_one": "{{animalNumber}}​ ពី {{count}}", + "OUT_OF_COUNT_other": "{{animalNumber}}​ ពី {{count}}", + "PLACEHOLDER": { + "BATCH_NAME": "វាយបញ្ចូលឈ្មោះជាក្រុម", + "DAM": "វាយបញ្ចូលទំនប់", + "NAME": "វាយបញ្ចូលឈ្មោះ", + "OTHER_DETAILS": "បញ្ចូលការពិពណ៌នា", + "OTHER_USE": "ពិពណ៌នាការប្រើប្រាស់ផ្សេងទៀត", + "PRICE": "វាមានតម្លៃប៉ុន្មាន?", + "SIRE": "វាយបញ្ចូលពូជបា", + "SUPPLIER": "វាយបញ្ចូលអ្នកផ្គត់ផ្គង់", + "TAG_COLOUR": "ស្លាកមានពណ៌អ្វី?", + "TAG_NUMBER": "វាយបញ្ចូលលេខស្លាក", + "TAG_TYPE": "តើស្លាកមានប្រភេទអ្វី?", + "TAG_TYPE_INFO": "សូមពិពណ៌នាប្រភេទស្លាករបស់អ្នក" + }, + "REMOVE_CONFIRM": "តើអ្នកពិតជាចង់លុបចេញមែនទេ?", + "SELECT_SEXES": "ជ្រើសរើសភេទ", + "SEX_DETAIL": "ព័ត៌មានលម្អិតអំពីភេទ", + "SEX_DETAIL_ERROR_one": "ចំនួនសត្វអតិបរមា៖ {{count}}", + "SEX_DETAIL_ERROR_other": "ចំនួនសត្វអតិបរមា៖ {{count}}", + "SEX_DETAIL_ERROR_POPOVER_one": "អ្នកមិនអាចមានសត្វលើសពី {{count}} ក្បាលបានទេ", + "SEX_DETAIL_ERROR_POPOVER_other": "អ្នកមិនអាចមានសត្វច្រើនជាង{{count}}​ ក្បាលបានទេ", + "SPECIFY_SEX": "បញ្ជាក់ពីភេទ", + "SUMMARY": { + "ADD_MORE_DETAILS": "បន្ថែមព័ត៌មានលម្អិតបន្ថែមអំពីសត្វរបស់អ្នក", + "ALL_DONE": "បញ្ចប់ទាំងស្រុង!", + "ANIMAL_SUMMARY_COUNT_one": "សត្វនីមួយ {{count}} ក្បាល", + "ANIMAL_SUMMARY_COUNT_other": "សត្វនីមួយ {{count}} ក្បាល", + "BATCH_SUMMARY_COUNT_one": "{{count}} ក្រុម", + "BATCH_SUMMARY_COUNT_other": "{{count}} ក្រុម", + "HERE_IS_SUMMARY": "នេះជាសេចក្តីសង្ខេបអំពីសត្វដែលអ្នកបានបន្ថែម៖", + "MAIN": "អ្នកបានបន្ថែម {{animalCount}} និង {{and}}{{batchCount}} ទៅក្នុងស្តុករបស់អ្នកដោយជោគជ័យ។" + }, + "TYPE": "វាយបញ្ចូល", + "UNIQUE_DETAILS": "ព័ត៌មានលម្អិតពិសេស" + }, + "ADD_FARM": { + "ADDRESS_IS_REQUIRED": "ត្រូវការអាសយដ្ឋាន", + "DISABLE_GEO_LOCATION": "ត្រូវបើកសេវាកម្មទីតាំង ដើម្បីរកទីតាំងបច្ចុប្បន្នរបស់អ្នក។", + "ENTER_A_VALID_ADDRESS": "សូមបញ្ចូលអាសយដ្ឋាន ឬកូអរដោនេតដែលត្រឹមត្រូវ", + "ENTER_LOCATION_PLACEHOLDER": "បញ្ចូលទីតាំង", + "FARM_IS_REQUIRED": "ត្រូវការឈ្មោះកសិដ្ឋាន", + "FARM_LOCATION": "ទីតាំងកសិដ្ឋាន", + "FARM_LOCATION_INPUT_INFO": "អាសយដ្ឋានផ្លូវ ឬ​សញ្ញាក្បៀសដែលបែងចែកកូអរដោនេតទទឹងនិងបណ្តោយ (ឧ. 49.250945, -123.238492)", + "FARM_NAME": "ឈ្មោះកសិដ្ឋាន", + "FARM_NAME_ERROR": "លើសកំណត់តួអក្សរឈ្មោះកសិដ្ឋាន", + "INVALID_FARM_LOCATION": "គ្មានប្រទេសសម្រាប់ទីតាំងនេះ", + "LOCATING": "កំពុងស្វែងរកទីតាំង...", + "TELL_US_ABOUT_YOUR_FARM": "ប្រាប់យើងអំពីកសិដ្ឋានរបស់អ្នក" + }, + "ADD_PRODUCT": { + "ADD_ANOTHER_PRODUCT": "បន្ថែមផលិតផលមួយទៀត", + "ADD_NEW_PRODUCT": "បន្ថែមផលិតផលថ្មី", + "ADDITIONAL_NUTRIENTS": "សារធាតុចិញ្ចឹមបន្ថែម", + "AMMONIUM": "អាម៉ូន្យូម (NH₄)", + "BORON": "ធាតុបូរ៉ុង (B)", + "BUTTON_WARNING": "ការផ្លាស់ប្តូរណាមួយនឹងប៉ះពាល់ដល់ភារកិច្ចទាំងអស់ដែលពាក់ព័ន្ធនឹងផលិតផលនេះ", + "CALCIUM": "កាល់ស្យូម (Ca)", + "COMPOSITION": "សមាសធាតុ", + "COMPOSITION_ERROR": "កំហុស៖ ភាគរយសរុបនៃ អាសូត​ ផូស្ព័រ​ ប៉ូតាស្យូម និងសារធាតុចិញ្ចឹមបន្ថែមមិនត្រូវលើស 100% ទេ។ សូមកែតម្រូវតម្លៃរបស់អ្នក។", + "COPPER": "ទង់ដែង​ (Cu)", + "DRY_FERTILISER": "ស្ងួត", + "DRY_MATTER_CONTENT": "បរិមាណសារធាតុស្ងួត", + "EDIT_PRODUCT_DETAILS": "កែសម្រួលព័ត៌មានផលិតផល", + "FERTILISER_TYPE": "ផលិតផលនេះស្ងួត ឬជារាវ?", + "LIQUID_FERTILISER": "រាវ", + "MAGNESIUM": "ម៉ាញេស្យូម (Mg)", + "MANGANESE": "ម៉ង់ហ្គាណែស (Mn)", + "MOISTURE_CONTENT": "បរិមាណសំណើម", + "NITRATE": "នីត្រាត (NO₃)", + "NITROGEN": "អាសូត (N)", + "PHOSPHOROUS": "ផូស្វ័រប៉េនតាអុកស៊ីត (P₂O₅)", + "POTASSIUM": "ប៉ូតាស្យូមអុកស៊ីត (K₂O)", + "PRESS_ENTER": "វាយបញ្ចូល ហើយចុច បញ្ចូល ដើម្បីបន្ថែម...", + "PRODUCT_DETAILS": "ព័ត៌មានលម្អិតផលិតផល", + "PRODUCT_LABEL": "ផលិតផល", + "SAVE_PRODUCT": "រក្សាទុកផលិតផល", + "SULFUR": "ស៊ុលហ្វួរ (S)", + "SUPPLIER_LABEL": "អ្នកផ្គត់ផ្គង់", + "WHAT_YOU_WILL_BE_APPLYING": "តើអ្នកនឹងប្រើអ្វី?" + }, + "ADD_TASK": { + "ADD_A_CUSTOM_TASK": "បន្ថែមភារកិច្ចផ្ទាល់ខ្លួន", + "ADD_A_TASK": "បន្ថែមកិច្ចការ", + "ADD_CUSTOM_TASK": "បន្ថែមភារកិច្ចផ្ទាល់ខ្លួន", + "AFFECT_PLANS": "តើភារកិច្ចនេះនឹងប៉ះពាល់ដល់ផែនការណាមួយទេ?", + "ASSIGN_ALL_TO_PERSON": "ផ្តល់ភារកិច្ចទាំងអស់នៅថ្ងៃនេះទៅឲ្យ {{name}}", + "ASSIGN_DATE": "ផ្លាស់ប្តូរកាលបរិច្ឆេទភារកិច្ច", + "ASSIGN_TASK": "ចាត់ភារកិច្ច", + "ASSIGNEE": "អ្នកទទួលភារកិច្ច", + "CANT_FIND_INFO_TASK": "អ្នកក៏អាចបង្កើតប្រភេទភារកិច្ចផ្ទាល់ខ្លួនរបស់អ្នកបានដែរ!", + "CLEANING_VIEW": { + "ESTIMATED_WATER": "ប៉ាន់ប្រមាណការប្រើប្រាស់ទឹក", + "IS_PERMITTED": "តើសារធាតុលាងសម្អាតមាននៅក្នុងបញ្ជីសារធាតុដែលអនុញ្ញាតទេ?", + "WHAT_NEEDS_TO_BE": "តើត្រូវសម្អាតអ្វី?", + "WILL_CLEANER_BE_USED": "តើនឹងប្រើសារធាតុលាងសម្អាត ឬសារធាតុសម្លាប់មេរោគទេ?" + }, + "CLEAR_ALL": "លុបទាំងអស់", + "CLEAR_ALL_PLANS": "សម្អាតផែនការទាំងអស់", + "CUSTOM_TASK": "ភារកិច្ចផ្ទាល់ខ្លួន", + "CUSTOM_TASK_CHAR_LIMIT": "ឈ្មោះប្រភេទភារកិច្ចផ្ទាល់ខ្លួនមិនអាចលើស 25 តួអក្សរបានទេ", + "CUSTOM_TASK_NAME": "ឈ្មោះភារកិច្ចផ្ទាល់ខ្លួន", + "CUSTOM_TASK_TYPE": "ប្រភេទភារកិច្ចផ្ទាល់ខ្លួន", + "DO_YOU_NEED_TO_OVERRIDE": "តើអ្នកត្រូវការប្ដូរប្រាក់ឈ្នួលអ្នកទទួលភារកិច្ចសម្រាប់ភារកិច្ចនេះទេ?", + "DO_YOU_WANT_TO_ASSIGN": "តើអ្នកចង់ចាត់ភារកិច្ចឥឡូវនេះទេ?", + "DUPLICATE_NAME": "ផលិតផលដែលមានឈ្មោះនេះមានរួចហើយ។ សូមជ្រើសរើសឈ្មោះផ្សេង។", + "EDIT_CUSTOM_TASK": "កែសម្រួលភារកិច្ចផ្ទាល់ខ្លួន", + "EDIT_TASK_WAGE": "កែប្រែប្រាក់ឈ្នួលភារកិច្ច", + "FIELD_WORK_VIEW": { + "OTHER_TYPE_OF_FIELD_WORK": "ពិពណ៌នាប្រភេទការងារនៅទីវាល", + "TYPE": { + "COVERING_SOIL": "គ្របដណ្តប់ដី", + "FENCING": "ការធ្វើរបង", + "OTHER": "ផ្សេងទៀត", + "PREPARING_BEDS_OR_ROWS": "ការរៀបចំរងដាំ ឬជួរដាំ", + "PRUNING": "ការកាត់មែក", + "SHADE_CLOTH": "ក្រណាត់បាំងម្លប់", + "TERMINATION": "ការបញ្ចប់ការងារ", + "TILLAGE": "ភ្ជួរដី", + "WEEDING": "ការដកស្មៅ" + }, + "TYPE_OF_FIELD_WORK": "ប្រភេទការងារនៅទីវាល" + }, + "GO_TO_CATALOGUE": "ចូលទៅកាន់កាតាឡុកដំណាំ", + "GO_TO_INVENTORY": "ទៅកាន់បញ្ជីសារពើភ័ណ្ឌ", + "HARVEST_EVERYTHING": "ប្រមូលផលទាំងអស់ដែលបានរួចរាល់", + "HARVESTING_INFO": "ផែនការនីមួយៗនឹងបង្កើតភារកិច្ចប្រមូលផលដាច់ដោយឡែកមួយ", + "HOURLY_WAGE": { + "ASSIGNEE_CURRENT_WAGE": "ប្រាក់ឈ្នួលម៉ោងរបស់ {{name}} គឺ {{wage}}/ម៉ោង", + "ASSIGNEE_WAGE_WARNING": "{{name}} មិនទាន់មានប្រាក់ឈ្នួលគិតជាម៉ោងដែលបានកំណត់នៅឡើយទេ។", + "DONT_ASK": "កុំសួរម្តងទៀតសម្រាប់បុគ្គលិកនេះ", + "FOR_THIS_TASK": "បាទ/ចាស សម្រាប់តែភារកិច្ចនេះប៉ុណ្ណោះ", + "SET_HOURLY_WAGE": "បាទ/ចាស កំណត់ប្រាក់ឈ្នួលម៉ោង", + "WANT_TO_SET_HOURLY_WAGE": "តើអ្នកចង់កំណត់ប្រាក់ឈ្នួលម៉ោងទេ?" + }, + "HOW_MUCH_IS_HARVESTED": "តើមានការប្រមូលផលប៉ុន្មាន?", + "HR": "/ម៉ោង", + "IRRIGATION_VIEW": { + "BRAND_TOOLTIP": "ភារកិច្ចនេះសម្រាប់ស្រោចទឹកទីតាំងរបស់អ្នក។ ប្រសិនបើអ្នកចង់ដំឡើងប្រព័ន្ធស្រោចទឹក សូមបង្កើតភារកិច្ចការងារនៅទីវាលវិញ។", + "CALCULATE_WATER_USAGE": "គណនាបរិមាណទឹកប្រើប្រាស់", + "CALCULATE_WATER_USAGE_WARNING": "សម្រាប់ដំណាំព្រៃ ការប៉ាន់ស្មានការប្រើប្រាស់ទឹកតាមជម្រៅមិនមានទេ។", + "DEFAULT_APPLICATION_DEPTH": "កំណត់ជាជម្រៅអនុវត្តលំនាំដើមសម្រាប់ទីតាំងនេះ", + "DEFAULT_LOCATION_FLOW_RATE": "កំណត់អត្រាលំហូរទឹកលំនាំដើមសម្រាប់ទីតាំងនេះ", + "DEPTH": "ជម្រៅ", + "ESTIMATED_APPLICATION_DEPTH": "ជម្រៅប្រើប្រាស់ដែលប៉ាន់ស្មាន", + "ESTIMATED_DURATION": "កំឡុងពេលប៉ាន់ប្រមាណ", + "ESTIMATED_FLOW_RATE": "អត្រាលំហូរដែលបានប៉ាន់ស្មាន", + "ESTIMATED_WATER_USAGE": "ការប្រើប្រាស់ទឹកដែលបានប៉ាន់ស្មាន", + "HOW_DO_YOU_MEASURE_WATER_USE_FOR_THIS_IRRIGATION_TYPE": "តើអ្នកវាស់ការប្រើប្រាស់ទឹកសម្រាប់ប្រព័ន្ធស្រោចទឹកប្រភេទនេះដូចម្តេច?", + "IRRIGATED_AREA": "តំបន់ស្រោចទឹក", + "IRRIGATION_TYPE_CHAR_LIMIT": "ប្រភេទប្រព័ន្ធស្រោចទឹកត្រូវតែមានតិចជាង 100 តួអក្សរ", + "LOCATION_SIZE": "ទំហំទីតាំង", + "NOT_SURE": "មិនប្រាកដ?", + "PERCENTAGE_LOCATION_TO_BE_IRRIGATED": "ភាគរយនៃទីតាំងដែលត្រូវស្រោចទឹក", + "SET_AS_DEFAULT_MEASUREMENT_FOR_THIS_IRRIGATION_TYPE": "កំណត់ជាការវាស់វែងលំនាំដើមសម្រាប់ប្រព័ន្ធស្រោចទឹកប្រភេទនេះ", + "SET_AS_DEFAULT_TYPE_FOR_THIS_LOCATION": "កំណត់ជាប្រភេទលំនាំដើមសម្រាប់ទីតាំងនេះ", + "TOTAL_WATER_USAGE": "ការប្រើប្រាស់សរុប", + "TYPE": { + "CHANNEL": "ប៉ុស្តិ៍", + "DRIP": "ស្រោចទឹកជាដំណក់", + "FLOOD": "ទឹកជំនន់", + "HAND_WATERING": "ស្រោចទឹកដោយដៃ", + "OTHER": "ផ្សេងទៀត", + "PIVOT": "ប្រព័ន្ធស្រោចទឹកបង្វិលកណ្ដាល", + "SPRINKLER": "ប្រព័ន្ធបាញ់ទឹកស្រោច", + "SUB_SURFACE": "ក្រោមផ្ទៃដី" + }, + "TYPE_OF_IRRIGATION": "ប្រភេទប្រព័ន្ធស្រោចស្រព", + "VOLUME": "បរិមាណ", + "WATER_USE_CALCULATOR": "ឧបករណ៍គណនាការប្រើប្រាស់ទឹក", + "WATER_USE_CALCULATOR_INFO": { + "PHRASE1": "ម៉ាស៊ីនគណនានេះជួយអ្នកគណនាការប្រើប្រាស់ទឹកដោយផ្អែកលើ​​ ", + "PHRASE2": "ប្រសិនបើអ្នកចង់គណនាដោយផ្អែកលើ", + "PHRASE3": "សូមត្រឡប់ទៅវិញ ហើយជ្រើសរើស" + }, + "WHAT_TYPE_OF_IRRIGATION": "ប្រព័ន្ធស្រោចទឹកប្រភេទណា?" + }, + "MANAGE_CUSTOM_TASKS": "គ្រប់គ្រងភារកិច្ចផ្ទាល់ខ្លួនរបស់អ្នក", + "MOVEMENT_VIEW": { + "MOVEMENT_PURPOSE_LABEL": "ចលនានេះមានគោលបំណងអ្វី?", + "MOVEMENT_PURPOSE_PLACEHOLDER": "ជ្រើសរើសគោលបំណងសម្រាប់ចលនានេះ", + "OTHER_PURPOSE_EXPLANATION_LABEL": "ការពន្យល់", + "OTHER_PURPOSE_EXPLANATION_PLACEHOLDER": "សូមពិពណ៌នាហេតុផលនៃចលនានេះ" + }, + "NEED_ANIMAL_LOCATION_MOVEMENT": "អ្នកត្រូវការទីតាំង ឬតំបន់សម្រាប់ផ្លាស់ទីសត្វ។ សូមទៅកាន់ផែនទី ដើម្បីបង្កើតទីតាំងសត្វ។", + "NEED_IRRIGATION_LOCATION": "ដើម្បីបង្កើតភារកិច្ចស្រោចស្រព អ្នកត្រូវមានទីតាំងដែលអាចដាំដំណាំបានជាមុនសិន។ សូមចូលទៅកាន់ផែនទីដើម្បីបង្កើតទីតាំងមួយ ដូចជា ដីដាំដំណាំ ផ្ទះកញ្ចក់ ឬតំបន់ការពារ។", + "NEED_IRRIGATION_LOCATION_WORKER": "អ្នកត្រូវមានសិទ្ធិគ្រប់គ្រង ដើម្បីបង្កើតទីតាំងដែលអាចដាំដំណាំបាន មុននឹងអាចបង្កើតភារកិច្ចស្រោចស្រពបាន។", + "NEED_MANAGEMENT_PLAN": "អ្នកត្រូវមានផែនការដំណាំដែលកំពុងដំណើរការ ឬបានរៀបចំទុកជាមុន មុននឹងអាចកំណត់ភារកិច្ចប្រមូលផល ឬដាំប្តូរបាន។ សូមទៅកាន់កាតាឡុកដំណាំ ដើម្បីបង្កើតផែនការឥឡូវនេះ។", + "NEED_SOIL_AMENDMENT_PRODUCTS": "ហាក់ដូចជាអ្នកមិនទាន់មានផលិតផលកែប្រែដីទេ។ សូមចូលទៅកាន់បញ្ជីស្តុក ដើម្បីបន្ថែមមួយ មុននឹងបង្កើតភារកិច្ចកែប្រែដី។", + "NEED_SOIL_SAMPLE_LOCATION": "អ្នកត្រូវមានទីតាំងជាក់លាក់ដែលបានកំណត់សម្រាប់យកសំណាកដី។ សូមចូលទៅកាន់ផែនទីដើម្បីបង្កើតទីតាំងយកសំណាកដី។", + "NEED_SOIL_SAMPLE_LOCATION_WORKER": "អ្នកត្រូវមានសិទ្ធិគ្រប់គ្រង ដើម្បីបង្កើតទីតាំងយកសំណាកដីយ៉ាងហោចណាស់មួយ មុននឹងអាចបង្កើតភារកិច្ចយកសំណាកដីបាន។", + "NO_ANIMAL_LOCATION": "មិនមានទីតាំងសត្វដែលអាចប្រើបានទេ", + "NO_IRRIGATION_LOCATIONS": "មិនមានទីតាំងសម្រាប់ស្រោចស្រពទេ", + "NO_MANAGEMENT_PLAN": "មិនមានផែនការដំណាំដែលអាចប្រើបានទេ", + "NO_SOIL_AMENDMENT_PRODUCTS": "សូមបន្ថែមផលិតផលកែប្រែដីជាមុនសិន", + "NO_SOIL_SAMPLE_LOCATION": "មិនមានទីតាំងយកសំណាកដីសមរម្យទេ", + "NOTES_LABEL": "មានអ្វីជាក់លាក់ដែលត្រូវបន្ថែមពាក់ព័ន្ធនឹងភារកិច្ចនេះទេ?", + "NOTES_PLACEHOLDER": "បន្ថែមការណែនាំ ឬព័ត៌មានលម្អិតសម្រាប់អ្នកទទួលភារកិច្ច", + "OFFLINE_NOTICE": { + "CANNOT_ADD_NEW": "អ្នកអាចប្រើទីតាំង ដំណាំ និងផលិតផលដែលមានស្រាប់ក្នុងភារកិច្ចរបស់អ្នកបាន ប៉ុន្តែមិនអាចបន្ថែមថ្មីបាននៅពេលនៅក្រៅបណ្ដាញ។", + "YOURE_OFFLINE": "អ្នកកំពុងនៅក្រៅបណ្តាញ" + }, + "PEST_CONTROL_VIEW": { + "BIOLOGICAL_CONTROL": "ការគ្រប់គ្រងជីវសាស្ត្រ", + "FLAME_WEEDING": "ការកំចាត់ស្មៅដោយភ្លើង", + "FOLIAR_SPRAY": "ការបាញ់ថ្នាំលើស្លឹក", + "HAND_WEEDING": "ការកំចាត់ស្មៅដោយដៃ", + "HEAT_TREATMENT": "ការកាត់មែក", + "IS_PERMITTED": "តើសារធាតុកំចាត់សត្វល្អិតមាននៅក្នុងបញ្ជីសារធាតុដែលអនុញ្ញាតទេ?", + "OTHER": "ផ្សេងទៀត", + "OTHER_PEST": "វិធីសាស្រ្តផ្សេងទៀត", + "PEST_CONTROL_METHOD": "វិធីសាស្ត្រគ្រប់គ្រងសត្វល្អិត", + "SOIL_FUMIGATION": "ការបាញ់ថ្នាំសម្លាប់មេរោគក្នុងដី", + "SYSTEMIC_SPRAY": "ការបាញ់ថ្នាំជាប្រព័ន្ធ", + "WHAT_PESTS": "តើអ្នកកំពុងព្យាយាមគ្រប់គ្រងសត្វល្អិត(ទាំងឡាយ)ណាខ្លះ" + }, + "PLANTING_FROM": "ដាំចាប់ពី", + "PLANTING_METHOD": "វិធីសាស្ត្រដាំ", + "PLANTING_STOCK": "សម្ភារៈដាំ", + "PLANTING_TASK": "កិច្ចការដាំដុះ", + "PLANTING_TASK_MODAL": "ការចាប់ផ្តើមភារកិច្ចដាំថ្មី នឹងបង្កើតផែនការដំណាំថ្មីមួយ។ សូមទៅកាន់កាតាឡុកដំណាំ ដើម្បីជ្រើសរើសដំណាំដែលអ្នកចង់ដាំ។", + "RETIRE_CUSTOM_TASK": "បញ្ឈប់ភារកិច្ចផ្ទាល់ខ្លួននេះទេ?", + "RETIRE_CUSTOM_TASK_CONTENT": "តើអ្នកប្រាកដថាចង់លុបភារកិច្ចផ្ទាល់ខ្លួននេះទេ?", + "SEED": "គ្រាប់", + "SELECT_ALL": "ជ្រើសរើសទាំងអស់", + "SELECT_ALL_PLANS": "ជ្រើសរើសផែនការទាំងអស់", + "SELECT_TASK_TYPE": "ជ្រើសរើសប្រភេទកិច្ចការ", + "SOIL_AMENDMENT_VIEW": { + "ADVANCED": "កម្រិតខ្ពស់", + "APPLICATION_METHOD": "វិធីសាស្ត្រប្រើប្រាស់", + "APPLICATION_RATE": "អត្រាប្រើប្រាស់", + "APPLIED_TO": "បានអនុវត្តលើ <1>{{percentOfArea}}% នៃ <4>{{locationArea}} {{locationAreaUnit}} {{locationType}} របស់អ្នក", + "APPLIED_TO_MULTIPLE": "បានអនុវត្តលើ <1>{{ percentOfArea }}% នៃទីតាំង {{locationCount}} របស់អ្នក ដែលមានផ្ទៃដីសរុប <5>{{ locationArea }} {{ locationAreaUnit }}", + "BANDED": "ដាក់ជាបន្ទះ", + "BROADCAST": "ផ្សព្វផ្សាយ", + "FERTIGATION": "ការដាក់ជីតាមទឹកស្រោច", + "FOLIAR": "លើស្លឹក", + "FURROW_HOLE": "រណ្តៅ/ជួរជីក", + "FURROW_HOLE_DEPTH": "ជម្រៅរណ្តៅ / ជម្រៅជួរជីក", + "FURROW_HOLE_DEPTH_PLACEHOLDER": "ការកែលម្អដីត្រូវបានអនុវត្តនៅជម្រៅប៉ុន្មាន?", + "IS_PERMITTED": "តើជីកែលម្អដីមាននៅក្នុងបញ្ជីសារធាតុដែលអនុញ្ញាតទេ?", + "MOISTURE_RETENTION": "ការរក្សាសំណើម", + "NUTRIENT_AVAILABILITY": "ភាពអាចប្រើបាននៃសារធាតុចិញ្ចឹម", + "OTHER": "ផ្សេងទៀត", + "OTHER_METHOD": "សូមប្រាប់បន្ថែមអំពីវិធីសាស្ត្រអនុវត្ត", + "OTHER_METHOD_PLACEHOLDER": "សូមពិពណ៌នាវិធីសាស្ត្រកែលម្អដីរបស់អ្នក...", + "OTHER_PURPOSE": "សូមពិពណ៌នាគោលបំណង", + "PERECENT_TO_AMEND": "ភាគរយនៃផ្ទៃដីទីតាំងដែលត្រូវកែលម្អ", + "PH": "កម្រិតអាស៊ីត-អាល់កាឡាំង​/pH", + "PURPOSE": "គោលបំនង", + "QUANTITY": "បរិមាណដែលត្រូវប្រើប្រាស់", + "SIDE_DRESS": "ដាក់ជីចំហៀង (លើផ្ទៃដី)", + "STRUCTURE": "រចនាសម្ព័ន្ធ", + "TOTAL_AREA": "ផ្ទៃដីសរុបដែលអនុវត្ត", + "VOLUME": "បរិមាណ", + "WEIGHT": "ទម្ងន់" + }, + "SOIL_SAMPLE_VIEW": { + "LOCATION_COUNT": "ចំនួនទីតាំងយកសំណាក", + "SAMPLE_DEPTH_RANGE": "ជួរជម្រៅសម្រាប់យកសំណាក #{{number}}", + "SAMPLE_PER_LOCATION_COUNT": "ចំនួនសំណាកក្នុងមួយទីតាំង", + "SAMPLE_TOOL": { + "AUGER": "ឧបករណ៍ខួងដី", + "SOIL_PROBE": "ឧបករណ៍យកសំណាកដី", + "SPADE": "ប៉ែល" + }, + "SAMPLING_TOOL": "ឧបករណ៍យកសំណាក" + }, + "TASK": "កិច្ចការ", + "TASK_NOTES_CHAR_LIMIT": "កំណត់ចំណាំត្រូវមានតិចជាង 10.000 តួអក្សរ", + "TASK_SPECIFIC_HOURLY_WAGE": "ប្រាក់ឈ្នួលម៉ោងតាមភារកិច្ច", + "TASK_WAGE": { + "NO_TASK_WAGE": "មិនមានកំណត់ប្រាក់ឈ្នួលសម្រាប់ភារកិច្ចនេះទេ", + "TASK_WAGE_SET": "ប្រាក់ឈ្នួលម៉ោងសម្រាប់ភារកិច្ចនេះត្រូវបានកំណត់ជា {{wage}} ក្នុងមួយម៉ោង", + "WANT_TO_SET_HOURLY_WAGE": "កំណត់ប្រាក់ឈ្នួលម៉ោងសម្រាប់ភារកិច្ចនេះតែមួយទេឬ?" + }, + "TELL_US_ABOUT_YOUR_TASK_TYPE_ONE": "សូមប្រាប់អំពីភារកិច្ចនេះ", + "THIS_TASK_IS_COMPLETED": "ភារកិច្ចនេះបានបញ្ចប់រួចហើយ", + "THIS_TASK_IS_COMPLETED_EXPLANATION": "ការចុច ‘រក្សាទុក’ នឹងរក្សាទុកភារកិច្ចនេះភ្លាមៗ។ បន្ទាប់មក អ្នកនឹងត្រូវបានស្នើឲ្យបញ្ចប់វា។", + "TRANSPLANT_METHOD": "វិធីសាស្ត្រស្ទូង", + "WAGE_OVERRIDE": "ការប្តូរប្រាក់ឈ្នួល", + "WHAT_PLANTING_METHOD": "វិធីសាស្ត្រស្ទូងគឺជាអ្វី?", + "WILD_CROP": "ដំណាំព្រៃ" + }, + "ADDON": { + "DISCONNECT_MODAL": { + "CANCEL": "កុំផ្តាច់ការតភ្ជាប់", + "CONFIRM": "ផ្តាច់ការតភ្ជាប់" + }, + "ESCI": { + "DISCONNECT_ESCI": "ផ្តាច់ការតភ្ជាប់ ESci", + "INFO": "អ្នកអាចផ្តាច់ការតភ្ជាប់សិនស័រ Ensemble Scientific ចេញពីកសិដ្ឋានរបស់អ្នកបាន។ វានឹងលុបសិនស័រទាំងអស់ចេញពី ESci។ ទោះជាយ៉ាងណា អ្នកនៅតែអាចចូលប្រើសិនស័រ និងទិន្នន័យដែលពាក់ព័ន្ធរបស់អ្នកនៅលើផ្ទាំងគ្រប់គ្រង ESci បាន។", + "MODAL_INFO": "អ្នកនឹងមិនអាចចូលប្រើទិន្នន័យសិនស័រ ESci របស់អ្នកបានទេ រហូតដល់អ្នកភ្ជាប់ឡើងវិញ", + "MODAL_TITLE": "តើអ្នកប្រាកដថាចង់ផ្តាច់ការតភ្ជាប់សិនស័រ ESci របស់អ្នកមែនទេ?" + }, + "ORGANISATION_ID": "លេខសម្គាល់អង្គភាព៖" + }, + "ANIMAL": { + "ADD_MORE_BODY_TEXT": "តើអ្នកមានប្រភេទសត្វផ្សេងទៀត ឬពូជផ្សេងទៀតទេ?", + "ADD_MORE_BUTTON": "បន្ថែមសត្វទៀត", + "ANIMAL_BREED": "ពូជសត្វ", + "ANIMAL_COUNT_one": "{{count}} សត្វ", + "ANIMAL_COUNT_other": "{{count}} សត្វ", + "ANIMAL_GROUPS": "ក្រុម", + "ANIMAL_ID": "លេខសម្គាល់", + "ANIMAL_IDENTIFICATION": "អត្តសញ្ញាណ", + "ANIMAL_LOCATIONS": "ទីតាំង", + "ANIMAL_SEXES": "ភេទ", + "ANIMAL_TYPE": "ប្រភេទ", + "ATTRIBUTE": { + "ANIMAL_IMAGE": "រូបសត្វ", + "BATCH_IMAGE": "បណ្តុំរូបភាព", + "BATCH_NAME": "ឈ្មោះជាក្រុម", + "DAM": "ទំនប់", + "DATE_OF_BIRTH": "ថ្ងៃខែឆ្នាំកំណើត", + "LITEFARM_ID": "អត្តសញ្ញាណ​​ ឡៃហ្វាម", + "ORGANIC_STATUS": "ស្ថានភាពសរីរាង្គ", + "OTHER_DETAILS_ANIMAL": "ព័ត៌មានលម្អិតសត្វផ្សេងទៀត", + "OTHER_DETAILS_BATCH": "ព័ត៌មានលម្អិតជាក្រុម", + "OTHER_USE": "ការប្រើប្រាស់ផ្សេងទៀត", + "SIRE": "ពូជបា", + "SUPPLIER": "អ្នកផ្គត់ផ្គង់", + "TAG_COLOUR": "ពណ៌ស្លាកសម្គាល់", + "TAG_NUMBER": "លេខស្លាកសម្គាល់", + "TAG_TYPE": "ប្រភេទស្លាកសម្គាល់", + "WEANING_DATE": "ថ្ងៃបញ្ឈប់ការបំបៅទឹកដោះ" + }, + "BATCH": "ក្រុម", + "BETA_SPOTLIGHT_HEADING": "ណែនាំមុខងារសត្វថ្មី", + "FILTER": { + "BATCHES": "ក្រុម", + "BATCHES_OR_INDIVIDUALS": "ក្រុម​រឺម្នាក់ៗ", + "FEMALE": "ញី", + "INDIVIDUALS": "ម្នាក់ៗ", + "MALE": "ឈ្មោល", + "TITLE": "តម្រងបង្ហាញតែសត្វ" + }, + "REMOVE_ANIMAL": "លុបសត្វ", + "SEARCH_INVENTORY_PLACEHOLDER": "ស្វែងរកក្នុងស្តុករបស់អ្នក", + "SHOWING_RESULTS_WITH_COUNT_one": "បង្ហាញ{{count}}លទ្ធផល", + "SHOWING_RESULTS_WITH_COUNT_many": "បង្ហាញ{{count}}លទ្ធផល", + "SHOWING_RESULTS_WITH_COUNT_other": "បង្ហាញ{{count}}លទ្ធផល", + "TABS": { + "BASIC_INFO": "ព័ត៌មានបឋម", + "TASKS": "កិច្ចការ" + } + }, + "BADGE": { + "BETA": { + "ANIMALS_BETA_CONTENT": "សូមមើលជាមុននូវមុខងារគ្រប់គ្រងសត្វថ្មីរបស់យើង—ឥឡូវនេះស្ថិតក្នុងដំណាក់កាលសាកល្បង! មតិយោបល់របស់អ្នកមានសារៈសំខាន់ខ្លាំងក្នុងការកែលម្អមុខងារនេះ។ សូមចែករំលែកកំហុស ឬសំណើកែលម្អណាមួយដែលអ្នកជួបប្រទះ។ យើងសូមអរគុណចំពោះការជួយរបស់អ្នកក្នុងការកែលម្អ ឡៃហ្វាម! អ្នកអាចស្វែងយល់បន្ថែមអំពីការសាកល្បងនេះ នៅទីនេះ", + "ANIMALS_BETA_HEADING": "សូមណែនាំមុខងារគ្រប់គ្រងសត្វថ្មី", + "ANIMALS_CONTENT": "សូមមើលមុខងារគ្រប់គ្រងសត្វថ្មីរបស់យើងជាមុន—ឥឡូវស្ថិតក្នុងដំណាក់កាលសាកល្បង! មតិយោបល់របស់អ្នកមានសារៈសំខាន់ខ្លាំងណាស់ក្នុងការកែលម្អមុខងារនេះ។ សូមចែករំលែកកំហុស ឬយោបល់ណាមួយដែលអ្នកជួបប្រទះ។ យើងសូមអរគុណចំពោះជំនួយរបស់អ្នកក្នុងការកែលម្អ​ ឡៃហ្វាម! អ្នកអាចស្វែងយល់បន្ថែមអំពីការសាកល្បង នៅទីនេះ", + "INVENTORY_BETA_CONTENT": "យើងកំពុងដាក់ឲ្យប្រើផ្នែកបញ្ជីសារពើភណ្ឌថ្មីក្នុងដំណាក់កាលសាកល្បង។ សម្រាប់ពេលនេះ អ្នកអាចតាមដានផលិតផលកែប្រែដីរបស់អ្នកបាន។ សាមញ្ញ និងមានប្រយោជន៍។ ប៉ុន្តែនេះគ្រាន់តែជាជំហានដំបូងប៉ុណ្ណោះ។ គោលដៅរបស់យើងគឺផ្តល់ឲ្យអ្នកនូវកន្លែងតែមួយសម្រាប់គ្រប់គ្រងអ្វីៗដែលកសិដ្ឋានរបស់អ្នកពឹងផ្អែកលើ ចាប់ពីឧបករណ៍ និងម៉ាស៊ីន រហូតដល់សម្ភារៈសម្អាត ការគ្រប់គ្រងសត្វល្អិត ចំណីសត្វ ដំណាំប្រមូលផល និងវត្ថុផ្ទាល់ខ្លួនផ្សេងៗរបស់អ្នក។ ដូចរាល់ដង មតិយោបល់របស់អ្នកជួយយើងកំណត់ទិសដៅបន្ត ដូច្នេះបើមានអ្វីមិនសមរម្យ ឬអ្នកមានគំនិតកែលម្អ សូមផ្ញើមកយើង។ អ្នកអាចស្វែងយល់បន្ថែមអំពីការសាកល្បង នៅទីនេះ", + "INVENTORY_BETA_HEADING": "សូមណែនាំផ្នែកសារពើភ័ណ្ឌ", + "TITLE": "ដំណាក់កាលសាកល្បង" + } + }, + "BED_PLAN": { + "LENGTH_OF_BED": "ប្រវែងរងដំណាំ", + "NUMBER_0F_BEDS": "ចំនួនរងដំណាំ", + "NUMBER_OF_ROWS": "ចំនួនជួររងដំណាំ", + "PLANT_SPACING": "ចន្លោះដាំ", + "PLANTING_DETAILS": "សូមបញ្ជាក់ព័ត៌មានលម្អិតនៃការដាំ" + }, + "BROADCAST_PLAN": { + "AREA_USED": "ផ្ទៃដីប្រើប្រាស់", + "HISTORICAL_PERCENTAGE_LOCATION": "តើប៉ុន្មានភាគរយនៃទីតាំងត្រូវបានដាំ?", + "LOCATION_SIZE": "ទំហំទីតាំង", + "PERCENTAGE_LABEL": "ភាគរយទីតាំង", + "PERCENTAGE_LOCATION": "តើអ្នកកំពុងដាំប៉ុន្មានភាគរយនៃទីតាំង?", + "PLANTING_NOTES": "កំណត់ចំណាំ​ការដាំ", + "SEEDING_RATE": "អត្រាប្រើគ្រាប់ពូជក្នុងការដាំ" + }, + "CANCEL_FLOW_MODAL": { + "BODY": "ព័ត៌មានទាំងអស់ដែលអ្នកបានបញ្ចូលនឹងត្រូវបានលុបចោល។ តើអ្នកចង់បន្តទេ?", + "NO_BUTTON": "កុំបោះបង់", + "TITLE": "តើអ្នកប្រាកដថាចង់បោះបង់មែនទេ?" + }, + "CERTIFICATION": { + "CERTIFICATION_EXPORT": { + "ADD": "បន្ថែមវិញ្ញាបនបត្រ", + "CHANGE_CERTIFICATION_PREFERENCE": "ប្ដូរវិញ្ញាបនបត្រដែលអ្នកចូលចិត្ត", + "CHANGE_CERTIFICATION_PREFERENCE_CAPITAL": "ប្ដូរវិញ្ញាបនបត្រដែលអ្នកចូលចិត្ត", + "NO_CERTIFICATIONS": "បច្ចុប្បន្ន អ្នកមិនកំពុងស្វែងរកវិញ្ញាបនបត្រណាមួយទេ។", + "NO_LONGER_WORKING": "លែងបន្តវិញ្ញាបនបត្រនេះ ឬធ្វើការជាមួយអ្នកចេញវិញ្ញាបនបត្រនេះទៀតហើយមែនទេ? មិនអីទេ!", + "SUPPORTED_CERTIFICATION_ONE": "អ្នកកំពុងបន្ត​ ", + "SUPPORTED_CERTIFICATION_TWO": " វិញ្ញាបនបត្រពី៖", + "UNSUPPORTED_CERTIFICATION_MESSAGE_ONE": "បច្ចុប្បន្ន ឡៃហ្វាម មិនបង្កើតឯកសារសម្រាប់អ្នកចេញវិញ្ញាបនបត្រនេះទេ។ ទោះយ៉ាងណា យើងអាចនាំចេញទម្រង់ទូទៅដែលមានប្រយោជន៍សម្រាប់អ្នកចេញវិញ្ញាបនបត្រភាគច្រើន។ អ្នកអាចជ្រើសរើស បញ្ជូន ដើម្បីបង្កើតទម្រង់ទាំងនេះ ឬ…​", + "UNSUPPORTED_CERTIFICATION_MESSAGE_TWO": "ដើម្បីពិនិត្យមើលថាតើមានអ្នកចេញវិញ្ញាបនបត្រថ្មីៗនៅតំបន់របស់អ្នកឬអត់។", + "UNSUPPORTED_CERTIFICATION_REQUEST_ONE": "អ្នកបានស្នើសុំ", + "UNSUPPORTED_CERTIFICATION_REQUEST_TWO": "វិញ្ញាបនបត្រពី", + "UPDATE_SUCCESS": "វិញ្ញាបនបត្រដែលអ្នកចូលចិត្តត្រូវបានរក្សាទុក" + }, + "CERTIFICATION_SELECTION": { + "REQUEST_CERTIFICATION": "ស្នើសុំវិញ្ញាបនបត្រប្រភេទផ្សេងទៀត", + "SUBTITLE_ONE": "នេះគឺជាបញ្ជីនៃ", + "SUBTITLE_TWO": "អ្នកចេញវិញ្ញាបនបត្រដែលយើងធ្វើការជាមួយនៅក្នុងប្រទេសរបស់អ្នក។", + "TITLE": "តើវិញ្ញាបនបត្រប្រភេទណា?", + "TOOLTIP": "មិនឃើញវិញ្ញាបនបត្ររបស់អ្នកទេឬ? ឡៃហ្វាម ប្តេជ្ញាគាំទ្រកសិកម្មប្រកបដោយនិរន្តរភាព ហើយវិញ្ញាបនបត្រជាផ្នែកសំខាន់មួយនៃការនេះ។ សូមស្នើសុំវិញ្ញាបនបត្រផ្សេងទៀតនៅទីនេះ ហើយយើងនឹងព្យាយាមបញ្ចូលវាទៅក្នុងកម្មវិធី។" + }, + "CERTIFIER_SELECTION": { + "INFO": "វាអាចមានន័យថា បច្ចុប្បន្ន ឡៃហ្វាម មិនទាន់ធ្វើការជាមួយអ្នកចេញវិញ្ញាបនបត្ររបស់អ្នកទេ—សូមអភ័យទោស! ទោះយ៉ាងណា ឡៃហ្វាម អាចបង្កើតទម្រង់ទូទៅដែលមានប្រយោជន៍សម្រាប់ករណីភាគច្រើន។", + "NOT_FOUND": "មិនឃើញអ្នកចេញវិញ្ញាបនបត្ររបស់អ្នកទេឬ?", + "REQUEST_CERTIFIER": "ស្នើសុំអ្នកចេញវិញ្ញាបនបត្រ", + "TITLE": "តើអ្នកចេញវិញ្ញាបនបត្ររបស់អ្នកជាអ្នកណា?" + }, + "INPUT_PLACEHOLDER": "វាយអក្សរដើម្បីស្វែងរក", + "INTERESTED_IN_CERTIFICATION": { + "PARAGRAPH": "តើអ្នកមានគម្រោងតាមយក ឬបន្តសុពលភាពវិញ្ញាបនបត្រនៅរដូវកាលនេះទេ?", + "TITLE": "ចាប់អារម្មណ៍លើវិញ្ញាបនបត្រទេ?", + "WHY_ANSWER": "ឡៃហ្វាម បង្កើតទម្រង់ដែលត្រូវការសម្រាប់វិញ្ញាបនបត្រសរីរាង្គ។ ព័ត៌មានមួយចំនួននឹងត្រូវបានទាមទារជាចាំបាច់។" + }, + "REQUEST_CERTIFIER": { + "LABEL": "អ្នកចេញវិញ្ញាបនបត្រដែលបានស្នើសុំ", + "REQUEST": "តើអ្នកចេញវិញ្ញាបនបត្រណាដែលអ្នកចង់ស្នើសុំ?", + "SORRY_ONE": "សូមអភ័យទោស — បច្ចុប្បន្នយើងមិនទាន់ធ្វើការជាមួយអ្នកណាម្នាក់ទេ", + "SORRY_THREE": "អ្នកចេញវិញ្ញាបនបត្រនៅក្នុងប្រទេសរបស់អ្នក។ តើអ្នកចង់ស្នើសុំមួយទេ?", + "SORRY_TWO": "អ្នកចេញវិញ្ញាបនបត្រ។ តើអ្នកចង់ស្នើសុំមួយទេ?", + "TITLE": "ស្នើសុំអ្នកចេញវិញ្ញាបនបត្រ" + }, + "SUMMARY": { + "BAD_NEWS": "បច្ចុប្បន្ន ឡៃហ្វាម មិនទាន់ប្រមូលព័ត៌មានដែលអ្នកត្រូវការសម្រាប់បង្កើតឯកសារវិញ្ញាបនបត្ររបស់អ្នកទេ—សូមអភ័យទោស!", + "BAD_NEWS_INFO": "ទោះយ៉ាងណា យើងអាចបង្កើតទម្រង់ទូទៅដែលមានប្រយោជន៍សម្រាប់អ្នកចេញវិញ្ញាបនបត្រភាគច្រើន។ យើងនឹងបង្ហាញព័ត៌មាននេះនៅទូទាំងកម្មវិធី ដោយប្រើរូបតំណាងស្លឹកឈើ។", + "CERTIFICATION": "វិញ្ញាបនបត្រ", + "GOOD_NEWS": "ដំណឹងល្អ! ឡៃហ្វាម អាចប្រមូលព័ត៌មានដែលអ្នកត្រូវការសម្រាប់បង្កើតឯកសារវិញ្ញាបនបត្ររបស់អ្នកបាន!", + "INFORMATION": "យើងនឹងបង្ហាញព័ត៌មាននេះនៅទូទាំងកម្មវិធី ដោយប្រើរូបតំណាងស្លឹកឈើ។", + "TITLE": "អ្នកមានចំណាប់អារម្មណ៍ក្នុងការដាក់ពាក្យសម្រាប់៖", + "YOUR_CERTIFICATION": "វិញ្ញាបនបត្ររបស់អ្នក" + } + }, + "CERTIFICATIONS": { + "COULD_NOT_CONTACT_CERTIFIER": "វាហាក់ដូចជា ឡៃហ្វាម បច្ចុប្បន្នមិនអាចបញ្ចូលក្នុងទម្រង់របស់អ្នកចេញវិញ្ញាបនបត្ររបស់អ្នកបានទេ។ ទោះយ៉ាងណា អ្នកនៅតែអាចបញ្ចូលឯកសាររបស់អ្នកបាន ប៉ុន្តែអ្នកចេញវិញ្ញាបនបត្រអាចត្រូវការព័ត៌មានបន្ថែម។ យើងនឹងផ្ញើវាទៅអ្នកនៅ៖", + "EXPORT": "បញ្ចូល​ / នាំចេញ", + "EXPORT_DOCS": "បញ្ចូលឯកសារវិញ្ញាបនបត្រ", + "EXPORT_DOWNLOADING_MESSAGE": "កំពុងទាញយកឯកសារវិញ្ញាបនបត្រសរីរាង្គរបស់អ្នក...", + "EXPORT_FILE_TITLE": "វិញ្ញាបនបត្រសរីរាង្គ", + "FILES_ARE_READY": "ឯកសារវិញ្ញាបនបត្ររបស់អ្នកបានត្រៀមរួចរាល់សម្រាប់នាំចេញហើយ។ យើងនឹងផ្ញើវាទៅអ្នកនៅ៖", + "GOOD_NEWS": "ដំណឹងល្អ!", + "HAVE_ALL_INFO": "វាហាក់ដូចជា ឡៃហ្វាម មានព័ត៌មានទាំងអស់ដែលយើងត្រូវការសម្រាប់ដំណើរការឯកសារវិញ្ញាបនបត្ររបស់អ្នក។ យើងនឹងផ្ញើវាទៅអ្នកនៅ៖", + "NEXT_WE_WILL_CHECK": "បន្ទាប់មក យើងនឹងពិនិត្យថាតើអ្នកចេញវិញ្ញាបនបត្ររបស់អ្នកត្រូវការព័ត៌មានបន្ថែមណាមួយសម្រាប់ដំណើរការការដាក់ស្នើវិញ្ញាបនបត្ររបស់អ្នកឬអត់។", + "NOTE_CANNOT_RESUBMIT": "ចំណាំ៖ នៅពេលអ្នកដាក់បញ្ចួនសំណួរស្ទង់មតិរួច អ្នកនឹងមិនអាចកែសម្រួលចម្លើយបានទៀតទេ។ ដើម្បីកែប្រែបន្ទាប់ពីដាក់ស្នើ សូមចាប់ផ្តើមការបញ្ចូលជាថ្មីម្តងទៀត។", + "ORGANIC_CERTIFICATION_FROM": "វិញ្ញាបនបត្រសរីរាង្គពី", + "SELECT_REPORTING_PERIOD": "ជ្រើសរើសរយៈពេលរាយការណ៍របស់អ្នក", + "UH_OH": "អុ​​​ អូ!", + "WOULD_LIKE_ANSWERS": "អ្នកត្រួតពិនិត្យឯកសាររបស់អ្នកចង់ឱ្យអ្នកឆ្លើយសំណួរមួយចំនួនបន្ថែមទៀត មុនពេលយើងអាចនាំចេញឯកសាររបស់អ្នកបាន។" + }, + "CERTIFICATIONS_MODAL": { + "MAYBE_LATER": "ប្រហែលជាលើកក្រោយ", + "STEP_ONE": { + "DESCRIPTION": "យើងបានបន្ថែមការគាំទ្រសម្រាប់វិញ្ញាបនបត្រ និងអ្នកចេញវិញ្ញាបនបត្រ! តើអ្នកចង់មើលថាតើមានអ្វីខ្លះនៅក្នុងតំបន់របស់អ្នកទេ?", + "TITLE": "មុខងារថ្មី!" + }, + "STEP_TWO": { + "DESCRIPTION": "មិនអីទេ! អ្នកអាចបន្ថែមវិញ្ញាបនបត្រ និងអ្នកចេញវិញ្ញាបនបត្រនៅពេលក្រោយ នៅក្រោម ‘កសិដ្ឋានរបស់ខ្ញុំ’។", + "TITLE": "មើលវិញ្ញាបនបត្រ" + } + }, + "CHOOSE_FARM": { + "ADD_NEW": "បន្ថែមកសិដ្ឋានថ្មី", + "CHOOSE_TITLE": "ជ្រើសរើសកសិដ្ឋានរបស់អ្នក", + "INPUT_PLACEHOLDER": "ស្វែងរក", + "SWITCH_TITLE": "ប្ដូរទៅកសិដ្ឋានផ្សេងទៀត" + }, + "COMMON_ERRORS": { + "UNIT": { + "NON_NEGATIVE": "ត្រូវតែជាលេខដែលមិនអវិជ្ជមាន", + "REQUIRED": "តម្រូវអោយ", + "TWO_DECIMALS": "បរិមាណត្រូវមានត្រឹម 2 ខ្ទង់ទសភាគ" + } + }, + "CONSENT": { + "DATA_POLICY": "គោលការណ៍ទិន្នន័យរបស់យើង", + "LABEL": "ខ្ញុំយល់ព្រម" + }, + "CREATE_USER": { + "BIRTH_YEAR": "ឆ្នាំកំណើត", + "BIRTH_YEAR_ERROR": "ឆ្នាំកំណើតត្រូវស្ថិតនៅចន្លោះ 1900 និង", + "BIRTH_YEAR_TOOLTIP": "ព័ត៌មានអាយុត្រូវបានប្រមូលសម្រាប់គោលបំណងស្រាវជ្រាវតែប៉ុណ្ណោះ ហើយនឹងត្រូវចែករំលែកដោយដកព័ត៌មានអត្តសញ្ញាណផ្ទាល់ខ្លួនចេញ", + "CREATE_BUTTON": "បង្កើតគណនី", + "DEFAULT_LANGUAGE": "ភាសាអង់គ្លេស", + "DEFAULT_LANGUAGE_VALUE": "km", + "EMAIL": "អុីម៉ែល", + "FULL_NAME": "ឈ្មោះពេញ", + "GENDER": "យេនឌ័រ", + "GENDER_TOOLTIP": "ព័ត៌មានយេនឌ័រត្រូវបានប្រមូលសម្រាប់គោលបំណងស្រាវជ្រាវតែប៉ុណ្ណោះ ហើយនឹងត្រូវចែករំលែកដោយដកព័ត៌មានអត្តសញ្ញាណផ្ទាល់ខ្លួនចេញ", + "LANGUAGE_PREFERENCE": "ចំណូលចិត្តភាសា", + "PASSWORD": "លេខសម្ងាត់", + "TITLE": "បង្កើតគណនីអ្នកប្រើថ្មី" + }, + "CROP": { + "ADD_CROP": "បន្ថែមដំណាំ", + "ADD_CROP_VARIETY": "បន្ថែមពូជដំណាំ", + "ADD_IMAGE": "បន្ថែមរូបភាពផ្ទាល់ខ្លួន", + "ANNUAL": "ប្រចាំឆ្នាំ", + "ANNUAL_OR_PERENNIAL": "ដំណាំនេះជាដំណាំប្រចាំឆ្នាំ ឬដំណាំអចិន្ត្រៃយ៍?", + "CULTIVAR_PLACEHOLDER": "ឧ. ដំណាំប៉មក្រហម", + "CULTIVAR_SUBTEXT": "ស្វែងយល់បន្ថែមអំពីពូជដំណាំ", + "DUPLICATE_VARIETY": "មានពូជដំណាំនេះដែលមានឈ្មោះដូចគ្នារួចហើយនៅក្នុងកសិដ្ឋានរបស់អ្នក", + "EDIT_CROP": "កែដំណាំ", + "EDIT_MODAL": { + "BODY": "ការកែប្រែដំណាំនេះ នឹងមិនប៉ះពាល់ដល់ផែនការដំណាំដែលមានស្រាប់ទេ។ មានតែផែនការដំណាំដែលបានបង្កើតបន្ទាប់ពីការកែប្រែប៉ុណ្ណោះដែលនឹងរងផលប៉ះពាល់។ តើអ្នកចង់បន្តការកែប្រែទេ?", + "TITLE": "កែដំណាំទេ?" + }, + "IS_GENETICALLY_ENGINEERED": "ដំណាំនេះត្រូវបានកែប្រែហ្សែនដែរឬទេ?", + "IS_ORGANIC": "គ្រាប់ពូជ ឬដំណាំនេះមានវិញ្ញាបនបត្រសរីរាង្គដែរឬទេ?", + "NEED_DOCUMENT_GENETICALLY_ENGINEERED": "ស្ថាប័នផ្តល់វិញ្ញាបនបត្ររបស់អ្នកអាចស្នើសុំឯកសារដើម្បីបញ្ជាក់ថា ដំណាំនេះមិនមែនជាដំណាំដែលបានកែប្រែហ្សែនទេ។", + "NEED_DOCUMENT_PERFORM_SEARCH": "អ្នកចេញវិញ្ញាបនបត្ររបស់អ្នកអាចស្នើសុំឯកសារគាំទ្រសម្រាប់ការស្វែងរករបស់អ្នកបាន។", + "NEED_DOCUMENT_TREATED": "អ្នកចេញវិញ្ញាបនបត្ររបស់អ្នកអាចស្នើសុំឯកសារពិពណ៌នាអំពីការព្យាបាលណាមួយបាន។", + "NUTRIENTS_IN_EDIBLE_PORTION": "សារធាតុចិញ្ចឹមក្នុងផ្នែកអាចបរិភោគបាន (ក្នុង 100 ក្រាម)", + "PERENNIAL": "ដំណាំអចិន្ត្រៃយ៍", + "PERFORM_SEARCH": "តើអ្នកបានធ្វើការស្វែងរកភាពមានលក់ក្នុងទីផ្សារដែរឬទេ?", + "PHYSIOLOGY_AND_ANATOMY": "សរីរវិទ្យា និងកាយវិភាគវិទ្យា", + "REPEAT_PLAN_MODAL": { + "DELETED_PLANS": "ផែនការដំណាំដែលបានលុប ដែលស្ថិតក្នុងការធ្វើឡើងវិញនេះ នឹងមិនត្រូវបានបង្ហាញទេ។" + }, + "TREATED": "គ្រាប់ពូជសម្រាប់ដំណាំនេះត្រូវបានព្យាបាលដែរឬទេ?", + "VARIETAL_IMAGE": "កំណត់រូបភាពផ្ទាល់ខ្លួនសម្រាប់ពូជ ឬពូជបង្កាត់", + "VARIETAL_IMAGE_INFO": "ប្រសិនបើអ្នកចង់ឱ្យពូជ ឬពូជបង្កាត់នេះមានរូបភាពផ្សេងពីរូបភាពដើមរបស់ដំណាំ អ្នកអាចប្ដូរតាមបំណងរូបភាពនៅទីនេះបាន។", + "VARIETAL_PLACEHOLDER": "ឧ. ទំពាំងបាយជូ​កាប៊ែរណេ សូវីញ៉ុង", + "VARIETAL_SUBTEXT": "ស្វែងយល់បន្ថែមអំពីពូជដំណាំ", + "VARIETAL_SUBTITLE": "សូមប្រាប់យើងអំពីពូជ ឬពូជបង្កាត់ជាក់លាក់ដែលអ្នកមានបំណងដាំ", + "VARIETY_COMMON_NAME": "ឈ្មោះទូទៅ", + "VARIETY_CULTIVAR": "ពូជបង្កាត់", + "VARIETY_VARIETAL": "ពូជ" + }, + "CROP_CATALOGUE": { + "ADD_CROP": "ពូជដំណាំ", + "ADD_CROPS_T0_YOUR_FARM": "បន្ថែមដំណាំថ្មី", + "ADD_TO_YOUR_FARM": "បន្ថែមទៅកសិដ្ឋានរបស់អ្នក", + "CAN_NOT_FIND": "រកមិនឃើញអ្វីដែលអ្នកកំពុងស្វែងរកទេឬ?", + "COVER_CROP": "ដំណាំនេះអាចដាំជាដំណាំគ្របដីបានដែរឬទេ?", + "CREATE_MANAGEMENT_PLANS": "បង្កើតផែនការដំណាំ", + "CROP_CATALOGUE": "កាតាឡុកដំណាំ", + "CROP_GROUP": "ក្រុមដំណាំ", + "CROP_GROUP_TOOL_TIP": "ការជ្រើសរើសក្រុមដំណាំអនុញ្ញាតឱ្យ ឡៃហ្វាម បំពេញព័ត៌មានជាមុនជាច្រើនអំពីដំណាំនេះ ដូចជា រដូវដាំ សារធាតុចិញ្ចឹម និងបរិមាណផលិតប្រចាំឆ្នាំប៉ាន់ស្មាន។ កុំបារម្ភ អ្នកអាចកែប្រែតម្លៃទាំងនេះខាងក្រោមបាន បន្ទាប់ពីបានជ្រើសរើសក្រុមដំណាំ។", + "DOCUMENT_NECESSARY_INFO_FOR_ORGANIC_PRODUCTION": "កត់ត្រាព័ត៌មានចាំបាច់សម្រាប់ផលិតផលសរីរាង្គ", + "DUPLICATE_CROP": "មានដំណាំមួយដែលមានឈ្មោះ, ប្រភេទពូជ និងប្រភេទជីវសាស្ត្រ ដូចគ្នារួចហើយនៅក្នុងកសិដ្ឋានរបស់អ្នក", + "FILTER": { + "LOCATION": "ទីតាំង", + "STATUS": "ស្ថានភាព", + "SUPPLIERS": "អ្នកផ្គត់ផ្គង់", + "TITLE": "តម្រងកាតាឡុកដំណាំ" + }, + "FILTER_TITLE": "តម្រងកាតាឡុកដំណាំ", + "GENUS": "ប្រភេទពូជ", + "HERE_YOU_CAN": "នៅទីនេះ អ្នកអាច៖", + "LETS_BEGIN": "សូមចាប់ផ្តើម", + "NEW_CROP_NAME": "ឈ្មោះដំណាំថ្មី", + "NO_RESULTS_FOUND": "រកមិនឃើញលទ្ធផលទេ។ សូមប្តូរតម្រងរបស់អ្នក។", + "NOMINATE_CROP": "ស្នើដំណាំនេះសម្រាប់បញ្ចូលក្នុងកាតាឡុកដំណាំ ឡៃហ្វាម", + "NOMINATE_CROP_TOOLTIP": "ការស្នើដំណាំនេះសម្រាប់បញ្ចូលក្នុងកាតាឡុកដំណាំ ឡៃហ្វាម ផ្តល់សិទ្ធិឱ្យក្រុមការងារ ឡៃហ្វាម ចែករំលែកព័ត៌មានអំពីដំណាំនេះជាមួយអ្នកជំនាញក្នុងតំបន់របស់អ្នក។ ដំណាំដែលបានអនុម័តនឹងក្លាយជាផ្នែកមួយនៃកាតាឡុកដំណាំ ដែលបង្ហាញដល់អ្នកប្រើប្រាស់ទាំងអស់។", + "ON_YOUR_FARM": "នៅកសិដ្ឋានរបស់អ្នក", + "SELECT_A_CROP": "ជ្រើសរើសដំណាំមួយដើម្បីបន្ថែមទៅកសិដ្ឋានរបស់អ្នក។ ប្រើការស្វែងរក និងតម្រង ដើម្បីរកដំណាំបានលឿនជាងមុន។", + "SPECIES": "ប្រភេទជីវសាស្ត្រ" + }, + "CROP_DETAIL": { + "ADD_PLAN": "បន្ថែមផែនការ", + "ANNUAL": "ប្រចាំឆ្នាំ", + "ANNUAL_PERENNIAL": "ដំណាំនេះជាដំណាំប្រចាំឆ្នាំ ឬអចិន្ត្រៃយ៍?", + "COMMERCIAL_AVAILABILITY": "តើអ្នកបានធ្វើការស្វែងរកភាពមានលក់ក្នុងទីផ្សារដែរឬទេ?", + "DETAIL_TAB": "ព័ត៌មានលំអិត", + "EDIT_CROP_DETAIL": "កែព័ត៌មានលំអិតដំណាំ", + "GENETICALLY_ENGINEERED": "ដំណាំនេះត្រូវបានកែប្រែហ្សែនដែរឬទេ?", + "HS_CODE": "លេខកូដ HS", + "MANAGEMENT_PLANS": "ផែនការដំណាំ", + "MANAGEMENT_TAB": "ការគ្រប់គ្រង", + "ORGANIC": "គ្រាប់ពូជ ឬដំណាំនេះមានវិញ្ញាបនបត្រសរីរាង្គដែរឬទេ?", + "PERENNIAL": "អចិន្ត្រៃយ៍", + "TREATED": "គ្រាប់ពូជសម្រាប់ដំណាំនេះត្រូវបានព្យាបាលដែរឬទេ?" + }, + "CROP_MANAGEMENT": { + "GERMINATE": "ដុះពន្លក", + "HARVEST": "ប្រមូលផល", + "PLANT": "រុក្ខជាតិ", + "SEED": "គ្រាប់", + "TERMINATE": "បញ្ឈប់", + "TRANSPLANT": "ស្ទូង" + }, + "CROP_STATUS_NON_ORGANIC_MISMATCH_MODAL": { + "SUBTITLE": "អ្នកបានបញ្ជាក់ថា អ្នកនឹងដាំដំណាំសរីរាង្គនៅទីតាំងមិនមែនសរីរាង្គ។ តើអ្នកចង់បន្តទេ?", + "TITLE": "អ្នកបានជ្រើសរើសទីតាំងមិនមែនសរីរាង្គ!" + }, + "CROP_STATUS_ORGANIC_MISMATCH_MODAL": { + "SUBTITLE": "អ្នកបានបញ្ជាក់ថា អ្នកនឹងដាំដំណាំមិនមែនសរីរាង្គនៅទីតាំងសរីរាង្គ។ តើអ្នកចង់បន្តទេ?", + "TITLE": "អ្នកបានជ្រើសរើសទីតាំងសរីរាង្គ!" + }, + "CROP_VARIETIES": { + "ADD_VARIETY": "បន្ថែមពូជថ្មី", + "CROP_VARIETIES": "ប្រភេទពូជ", + "RETIRE": { + "CONFIRMATION": "ការដកដំណាំនេះចេញនឹងលុបវា និងផែនការដំណាំទាំងអស់របស់វាចេញពីកាតាឡុកដំណាំរបស់អ្នក។ តើអ្នកចង់បន្តទេ?", + "RETIRE_CROP_TITLE": "ដកដំណាំចេញ?", + "UNABLE_TO_RETIRE": "អ្នកអាចដកដំណាំចេញបានតែដំណាំដែលគ្មានផែនការដំណាំសកម្ម ឬផែនការអនាគតប៉ុណ្ណោះ។ អ្នកត្រូវបញ្ចប់ ឬបោះបង់ផែនការទាំងនោះសិន ដើម្បីដកដំណាំនេះចេញ", + "UNABLE_TO_RETIRE_TITLE": "មិនអាចដកចេញ" + }, + "SUPPLIER": "អ្នកផ្គត់ផ្គង់", + "TITLE": "{{crop_name}} ពូជដំណាំ" + }, + "DATE_RANGE": { + "INVALID_RANGE_MESSAGE": "កាលបរិច្ឆេទបញ្ចប់ត្រូវតែបន្ទាប់ពីកាលបរិច្ឆេទចាប់ផ្តើម ដើម្បីទទួលបានលទ្ធផល" + }, + "DATE_RANGE_PICKER": { + "FROM": "ពី", + "REVENUE_HELP_BODY": "មានតែផែនការដែលមានភារកិច្ចប្រមូលផលដែលបានគ្រោងទុក ឬបានបញ្ចប់ ក្នុងចន្លោះកាលបរិច្ឆេទដែលបានបញ្ជាក់ប៉ុណ្ណោះ នឹងត្រូវបង្ហាញ។", + "REVENUE_HELP_TITLE": "ជំនួយចន្លោះកាលបរិច្ឆេទ", + "TO": "ទៅ", + "TO_MUST_BE_AFTER_FROM": "កាលបរិច្ឆេទ ‘ទៅ’ ត្រូវតែបន្ទាប់ពីកាលបរិច្ឆេទ ‘ពី’" + }, + "DATE_RANGE_SELECTOR": { + "BACK": "ត្រឡប់ក្រោយ", + "CLEAR_DATES": "លុបកាលបរិច្ឆេទ", + "CUSTOM_RANGE": "ជ្រើសរើសចន្លោះកាលបរិច្ឆេទផ្ទាល់ខ្លួន", + "LAST_12_MONTHS": "12 ខែចុងក្រោយ", + "LAST_FOURTEEN_DAYS": "14 ថ្ងៃចុងក្រោយ", + "LAST_MONTH": "ខែមុន", + "LAST_SEVEN_DAYS": "7 ថ្ងៃក្រោយ", + "LAST_THIRTY_DAYS": "30 ថ្ងៃក្រោយ", + "LAST_WEEK": "សប្តាហ៏មុន", + "THIS_MONTH": "ខែនេះ", + "THIS_WEEK": "សប្តាហ៏េនេះ", + "YEAR_TO_DATE": "ចាប់ពីដើមឆ្នាំដល់បច្ចុប្បន្ន" + }, + "DAYS_OF_WEEK_SELECT": { + "FRIDAY": "ថ្ងៃសុក្រ", + "MONDAY": "ថ្ងៃច័ន្ទ", + "SATURDAY": "ថ្ងៃអង្គារ", + "SUNDAY": "ថ្ងៃអាទិត្យ", + "THURSDAY": "ថ្ងៃព្រហស្បតិ៍", + "TUESDAY": "ថ្ងៃអង្គារ", + "WEDNESDAY": "ថ្ងៃពុធ" + }, + "DIRECTION": { + "E": "ទិសខាងកើត", + "ENE": "ទិសឦសានឆៀងខាងកើត", + "ESE": "ទិសអាគ្នេយ៍ឆៀងខាងកើត", + "N": "ទិសខាងជើង", + "NE": "ទិសឦសាន", + "NNE": "ទិសឦសានឆៀងខាងជើង", + "NNW": "ទិសពាយ័ព្យឆៀងខាងជើង", + "NW": "ទិសពាយ័ព្យ", + "S": "ទិសខាងត្បូង", + "SE": "ទិសអាគ្នេយ៍", + "SSE": "ទិសអាគ្នេយ៍ឆៀងខាងត្បូង", + "SSW": "ទិសនិរតីឆៀងខាងត្បូង", + "SW": "ទិសខាងត្បូងឆៀងខាងលិច", + "W": "ទិសខាងលិច", + "WNW": "ទិសពាយ័ព្យឆៀងខាងលិច", + "WSW": "ទិសនិរតីឆៀងខាងលិច" + }, + "DOCUMENTS": { + "ADD": { + "ADD_MORE_PAGES": "បន្ថែមទំព័រទៀត", + "DOCUMENT_NAME": "ឈ្មោះឯកសារ", + "DOES_NOT_EXPIRE": "ឯកសារនេះមិនមានថ្ងៃផុតកំណត់ទេ", + "TITLE": "បន្ថែមឯកសារ", + "TYPE": "វាយបញ្ចូល", + "VALID_UNTIL": "មានសុពលភាពរហូតដល់" + }, + "ADD_DOCUMENT": "បន្ថែមឯកសារថ្មី", + "ARCHIVE": "ទុកក្នុងបណ្ណសារ", + "ARCHIVE_DOCUMENT": "ទុកឯកសារនេះក្នុងបណ្ណសារ?", + "ARCHIVE_DOCUMENT_TEXT": "ការទុកឯកសារនេះក្នុងបណ្ណសារ នឹងផ្លាស់ទីវាទៅផ្នែកឯកសារដែលបានទុកក្នុងបណ្ណសារ ប៉ុន្តែមិនលុបវាទេ។ ឯកសារដែលបានទុកក្នុងបណ្ណសារ នឹងមិនត្រូវបាននាំចេញសម្រាប់វិញ្ញាបនបត្ររបស់អ្នកទេ។ តើអ្នកចង់បន្តទេ?", + "ARCHIVED": "បានទុកក្នុងបណ្ណសារ", + "CANCEL": "បោះបង់", + "COMPLIANCE_DOCUMENTS_AND_CERTIFICATION": "ឯកសារអនុលោមតាមស្តង់ដារ និងវិញ្ញាបនបត្ររបស់អ្នក", + "DOCUMENTS": "ឯកសារ", + "EDIT_DOCUMENT": "កែឯកសារ", + "FILTER": { + "TITLE": "តម្រងឯកសារ", + "TYPE": "វាយបញ្ចូល", + "VALID_ON": "មានសុពលភាពនៅថ្ងៃទី" + }, + "NOTES_CHAR_LIMIT": "កំណត់ចំណាំត្រូវមានតិចជាង 10.000 តួអក្សរ", + "SPOTLIGHT": { + "CDC": "នៅពេលដល់ពេលបង្កើតការនាំចេញវិញ្ញាបនបត្រ ឡៃហ្វាម នឹងនាំចេញដោយស្វ័យប្រវត្តិឯកសារអនុលោមតាមស្តង់ដាទាំងអស់ដែលមានសុពលភាពនៅថ្ងៃនាំចេញដែលអ្នកបានកំណត់។ ឯកសារអនុលោមភាពនឹងត្រូវបានដាក់ក្នុងបណ្ណសារដោយស្វ័យប្រវត្តិ នៅពេលវាផុតកំណត់។", + "HERE_YOU_CAN": "នៅទីនេះអ្នកអាច៖", + "YOU_CAN_ONE": "ផ្ទុកឡើងឯកសារដែលអ្នកចង់បញ្ចូលក្នុងការនាំចេញវិញ្ញាបនបត្ររបស់អ្នក", + "YOU_CAN_THREE": "ដាក់ឯកសារដែលមិនចាំបាច់ក្នុងបណ្ណសារ", + "YOU_CAN_TWO": "ចាត់ថ្នាក់ និងតាមដានកាលបរិច្ឆេទផុតកំណត់របស់ឯកសាររបស់អ្នក" + }, + "TYPE": { + "CLEANING_PRODUCT": "ផលិតផលសំអាត", + "CROP_COMPLIANCE": "ការអនុលោមតាមស្តង់ដាររបស់ដំណាំ", + "FERTILIZING_PRODUCT": "ផលិតផលជី", + "INVOICES": "វិក្កយបត្រ", + "OTHER": "ផ្សេងទៀត", + "PEST_CONTROL_PRODUCT": "ផលិតផលកំចាត់សត្វល្អិត", + "RECEIPTS": "បង្កាន់ដៃទូទាត់ប្រាក់", + "SOIL_AMENDMENT": "ការកែលំអរដី", + "SOIL_SAMPLE_RESULTS": "លទ្ធផលសំណាកដី", + "WATER_SAMPLE_RESULTS": "លទ្ធផលសំណាកទឹក" + }, + "UNARCHIVE": "យកចេញពីបណ្ណសារ", + "UNARCHIVE_DOCUMENT": "យកឯកសារនេះចេញពីបណ្ណសារ?", + "UNARCHIVE_DOCUMENT_TEXT": "ការយកឯកសារនេះចេញពីបណ្ណសារ នឹងបញ្ចូលវាត្រឡប់ទៅក្នុងបញ្ជីឯកសារដែលមានសុពលភាពបច្ចុប្បន្នរបស់អ្នក។ ឯកសារដែលមានសុពលភាពនឹងត្រូវបាននាំចេញសម្រាប់វិញ្ញាបនបត្ររបស់អ្នក។ តើអ្នកចង់បន្តទេ?", + "VALID": "សុពលភាព" + }, + "ENTER_PASSWORD": { + "FORGOT": "ភ្លេចលេខកូដសម្ងាត់?", + "HINT": "តម្រុយ", + "LABEL": "លេខកូដសម្ងាត់", + "ONE_NUMBER": "យ៉ាងហោចណាស់មួយលេខ", + "ONE_SPECIAL_CHARACTER": "យ៉ាងហោចណាស់តួអក្សរពិសេសមួយ​​ (! @ # $ % ^ &)", + "ONE_UPPER_CASE": "ត្រូវមានតួអក្សរអក្សរធំយ៉ាងហោចណាស់មួយ", + "TOO_SHORT": "ត្រូវមានយ៉ាងហោចណាស់ 8 តួអក្សរ" + }, + "ENTITY_TYPES": { + "LOCATION": "ទីតាំង", + "TASK": "កិច្ចការ" + }, + "ERROR_FALLBACK": { + "CONTACT": "នៅតែជាប់គាំងមែនទេ? កុំបារម្ភ យើងនៅទីនេះដើម្បីជួយអ្នក៖ <1>{{supportEmail}}", + "MAIN": "ពេលខ្លះ ឡៃហ្វាម អាចមានបញ្ហា ហើយត្រូវការជំនួយបន្តិចបន្តួច។ ជាទូទៅ វិធីខាងក្រោមមួយអាចដោះស្រាយបញ្ហាបាន៖", + "RELOAD": "ផ្ទុកទំព័រឡើងវិញ", + "SUBTITLE": "កុំបារម្ភ វាមិនមែនជាបញ្ហារបស់អ្នកទេ វាជាបញ្ហារបស់យើង។", + "TITLE": "អូហូ! ទំព័រនេះហាក់ដូចជាបានបាត់ទៅហើយ!" + }, + "EXPENSE": { + "ADD_EXPENSE": { + "ADD_CUSTOM_EXPENSE": "បន្ថែមចំណាយផ្ទាល់ខ្លួន", + "ADD_CUSTOM_EXPENSE_TYPE": "បន្ថែមប្រភេទចំណាយផ្ទាល់ខ្លួន", + "CUSTOM_EXPENSE_NAME": "ឈ្មោះចំណាយផ្ទាល់ខ្លួន", + "CUSTOM_EXPENSE_TYPE": "ប្រភេទចំណាយផ្ទាល់ខ្លួន", + "DUPLICATE_NAME": "មានប្រភេទចំណាយដែលមានឈ្មោះនេះរួចហើយ។ សូមជ្រើសរើសឈ្មោះផ្សេង។", + "DUPLICATE_NAME_RETIRED": "មានប្រភេទចំណាយដែលបានដកចេញដែលមានឈ្មោះនេះរួចហើយ។ សូមជ្រើសរើសឈ្មោះផ្សេង។", + "MANAGE_CUSTOM_EXPENSE_TYPE": "គ្រប់គ្រងប្រភេទចំណាយផ្ទាល់ខ្លួន", + "NEW_EXPENSE_ITEM": "បញ្ជីចំណាយថ្មី", + "TITLE": "បន្ថែមចំណាយ", + "WHICH_TYPES_TO_RECORD": "ជ្រើសរើសប្រភេទចំណាយរបស់អ្នកខាងក្រោម៖" + }, + "CUSTOM_EXPENSE_DESCRIPTION": "ការពិពណ៌នាចំណាយផ្ទាល់ខ្លួន", + "DELETE": { + "CONFIRM": "បញ្ជាក់ការលុប", + "HEADER": "លុបចំណាយនេះទេ?", + "LINK": "លុបចំណាយនេះ", + "MESSAGE": "ការនេះនឹងលុបចំណាយចេញពីកំណត់ត្រាកសិដ្ឋានរបស់អ្នក។ វានឹងមិនត្រូវបានបង្ហាញក្នុងសេចក្តីសង្ខេបហិរញ្ញវត្ថុណាមួយទៀតទេ។" + }, + "DETAILED_HISTORY": "ប្រវត្តិលម្អិត", + "EDIT_EXPENSE": { + "RETIRE_EXPENSE_MESSAGE": "ការដកប្រភេទចំណាយនេះចេញ នឹងលុបវាចេញពីជម្រើសសម្រាប់ចំណាយអនាគត។ ទោះជាយ៉ាងណា អ្នកនៅតែអាចស្វែងរក និងតម្រងករណីប្រវត្តិនៃប្រភេទចំណាយនេះនៅក្នុងផ្ទាំងហិរញ្ញវត្ថុបាន។", + "RETIRE_EXPENSE_TYPE": "ដកប្រភេទចំណាយចេញ", + "RETIRED": "(ដកចេញ)", + "TITLE": "កែចំណាយ", + "TITLE_1": "កែចំណាយ​​ (1 នៃ 2)", + "TITLE_2": "កែចំណាយ​​ (2 នៃ 2)" + }, + "ENTITY_SECTION": { + "ENTITY_ASSOCIATION_LABEL": "តើការចំណាយនេះទាក់ទងនឹងសត្វ ឬដំណាំ?", + "EXCEEDED_ERROR": "ចំនួនទឹកប្រាក់ដែលប្រើប្រាស់ មិនអាចលើសពីចំនួនទឹកប្រាក់សរុបដែលត្រូវបែងចែកបានឡើយ", + "SELECT_ANIMALS": "សូមជ្រើសរើសសត្វពីបញ្ជីសារពើភណ្ឌរបស់អ្នក", + "TOTAL_TO_ALLOCATE": "ចំនួនសរុបសម្រាប់បែងចែក" + }, + "ITEM_NAME": "បញ្ជីឈ្មោះ", + "NO_EXPENSE": "រកមិនឃើញចំណាយទេ", + "NO_EXPENSE_YEAR": "អ្នកមិនមានកំណត់ត្រាចំណាយសម្រាប់ឆ្នាំនេះទេ", + "OTHER_EXPENSES_TITLE": "ចំណាយផ្សេងទៀត", + "SUMMARY": "សង្ខេប", + "TYPE": "ប្រភេទ", + "VALUE": "តម្លៃ" + }, + "EXPIRED_TOKEN": { + "RESET_PASSWORD": "តំណភ្ជាប់នេះបានផុតកំណត់ហើយ។", + "RESET_PASSWORD_LINK": "ផ្ញើតំណកំណត់ពាក្យសម្ងាត់ថ្មី។" + }, + "FARM_MAP": { + "ADD_LOCATION": "បន្ថែមទីតាំង", + "AREA_DETAILS": { + "NETWORK": "បញ្ហាការតភ្ជាប់បណ្តាញ។", + "PERIMETER": "បរិមាណជុំវិញ", + "TOTAL_AREA": "តំបន់សរុប" + }, + "BARN": { + "ANIMALS": "តើតំបន់នេះត្រូវបានប្រើសម្រាប់ការចិញ្ចឹមសត្វដែរឬទេ?", + "COLD_STORAGE": "តើរោងសត្វនេះមានបន្ទប់ត្រជាក់សម្រាប់រក្សាទុកដែរឬទេ?", + "EDIT_TITLE": "កែរោងសត្វ", + "NAME": "ឈ្មោះរោងសត្វ", + "TITLE": "បន្ថែមរោងសត្វ", + "WASH_PACK": "តើរោងសត្វនេះមានស្ថានីយលាង និងវេចខ្ចប់ដែរឬទេ?" + }, + "BUFFER_ZONE": { + "EDIT_TITLE": "កែតំបន់ទប់ស្កាត់", + "NAME": "ឈ្មោះតំបន់ទប់ស្កាត់", + "TITLE": "បន្ថែមតំបន់ទប់ស្កាត់", + "WIDTH": "ទទឹងតំបន់ទប់ស្កាត់" + }, + "CEREMONIAL_AREA": { + "EDIT_TITLE": "កែប្រែតំបន់ពិធីបុណ្យ", + "NAME": "ឈ្មោះតំបន់ពិធីបុណ្យ", + "TITLE": "បន្ថែមតំបន់ពិធីបុណ្យ" + }, + "CONFIRM_RETIRE": { + "BODY": "ការដកទីតាំងនេះចេញ នឹងលុបវាចេញពីផែនទីកសិដ្ឋាន។", + "TITLE": "ដកទីតាំងចេញ?" + }, + "DRAWING_MANAGER": { + "REDRAW": "គូរឡើងវិញ", + "ZERO_AREA_DETECTED": "មិនបានរកឃើញផ្ទៃវាលទេ។ សូមបន្ថែមចំណុចទៅលើគំនូរបច្ចុប្បន្ន ឬគូរឡើងវិញ។", + "ZERO_LENGTH_DETECTED": "មិនបានរកឃើញប្រវែងបន្ទាត់ទេ។ សូមគូរឡើងវិញ។" + }, + "EXPORT_MAP": "ទាញយកផែនទី", + "EXPORT_MODAL": { + "BODY": "តើអ្នកចង់នាំចេញផែនទីកសិដ្ឋានរបស់អ្នកដោយរបៀបណា?", + "DOWNLOAD": "ទាញយក", + "EMAIL_TO_ME": "ផ្ញើអ៊ីមែលមកខ្ញុំ", + "EMAILING": "កំពុងផ្ញើអ៊ីមែល", + "TITLE": "នាំចេញផែនទីកសិដ្ឋានរបស់អ្នក" + }, + "FARM_SITE_BOUNDARY": { + "EDIT_TITLE": "កែប្រែព្រំដែនទីតាំងកសិដ្ឋាន", + "NAME": "ឈ្មោះព្រំដែនទីតាំងកសិដ្ឋាន", + "TITLE": "បន្ថែមព្រំដែនទីតាំងកសិដ្ឋាន" + }, + "FENCE": { + "EDIT_TITLE": "កែរបង", + "LENGTH": "ប្រវែងសរុប", + "NAME": "ឈ្មោះរបង", + "PRESSURE_TREATED": "តើរបងនេះបានដាក់ការពារសម្ពាធដែរឬទេ?", + "TITLE": "បន្ថែមរបង" + }, + "FIELD": { + "DATE": "កាលបរិច្ឆេទអនុគ្រោះសម្រាប់ការផ្លាស់ប្តូរ", + "EDIT_TITLE": "កែទីវាល", + "FIELD_TYPE": "តើទីវាលនេះជាប្រភេទអ្វី?", + "NAME": "ឈ្មោះទីវាល/ឈ្មោះចម្ការ", + "NON_ORGANIC": "មិនមែនសរីរាង្គ", + "ORGANIC": "សរីរាង្គ", + "TITLE": "បន្ថែមទីវាល/បន្ថែមចម្ការ", + "TRANSITIONING": "កំពុងផ្លាស់ប្តូរ" + }, + "FILTER_MAP": "បង្ហាញព័ត៌មានផែនទី", + "GARDEN": { + "DATE": "កាលបរិច្ឆេទអនុគ្រោះសម្រាប់ការផ្លាស់ប្តូរ", + "EDIT_TITLE": "កែសួនច្បារ", + "GARDEN_TYPE": "តើសួនច្បារនេះជាប្រភេទអ្វី?", + "NAME": "ឈ្មោះសួនច្បារ", + "NON_ORGANIC": "មិនមែនសរីរាង្គ", + "ORGANIC": "សរីរាង្គ", + "TITLE": "បន្ថែមសួនច្បារ", + "TRANSITIONING": "កំពុងផ្លាស់ប្តូរ" + }, + "GATE": { + "EDIT_TITLE": "កែទ្វារ", + "NAME": "ឈ្មោះទ្វារ", + "TITLE": "បន្ថែមទ្វារ" + }, + "GREENHOUSE": { + "CO2_ENRICHMENT": "តើមានការបន្ថែម ឧស្ម័នកាបូនឌីអុកស៊ីត ដែរឬទេ?", + "DATE": "កាលបរិច្ឆេទអនុគ្រោះសម្រាប់ការផ្លាស់ប្តូរ", + "EDIT_TITLE": "កែប្រែផ្ទះកញ្ចក់", + "GREENHOUSE_HEATED": "តើផ្ទះកញ្ចក់នេះមានប្រព័ន្ធកំដៅដែរឬទេ?", + "GREENHOUSE_TYPE": "តើផ្ទះកញ្ចក់នេះជាប្រភេទអ្វី?", + "NAME": "ឈ្មោះផ្ទះកញ្ចក់", + "NON_ORGANIC": "មិនមែនសរីរាង្គ", + "ORGANIC": "សរីរាង្គ", + "SUPPLEMENTAL_LIGHTING": "តើមានភ្លើងបន្ថែមដែរឬទេ?", + "TITLE": "បន្ថែមផ្ទះកញ្ចក់", + "TRANSITIONING": "កំពុងផ្លាស់ប្តូរ" + }, + "LINE_DETAILS": { + "BUFFER_TITLE": "ទទឹងប៉ុន្មាន?", + "BUFFER_ZONE_WIDTH": "ទទឹងតំបន់ទប់ស្កាត់", + "RIPARIAN_BUFFER": "តំបន់ការពារទឹក", + "WATERCOURSE": "ផ្លូវទឹក", + "WATERCOURSE_TITLE": "តើទទឹងខាងក្រោមមានអ្វីខ្លះ?" + }, + "MAP_FILTER": { + "ADD_TITLE": "បន្ថែមទៅផែនទីរបស់អ្នក", + "AREAS": "តំបន់", + "BARN": "រោងសត្វ", + "BUFFER_ZONE": "តំបន់ទប់ស្កាត់", + "BZ": "តំបន់ទប់ស្កាត់", + "CA": "តំបន់ពិធីបុណ្យ", + "CEREMONIAL_AREA": "តំបន់ពិធីបុណ្យ", + "FARM_SITE_BOUNDARY": "ព្រំដែនទីតាំងកសិដ្ឋាន", + "FENCE": "របង", + "FIELD": "ទីវាល/ចម្ការ", + "FSB": "ព្រំដែនទីតាំងកសិដ្ឋាន", + "GARDEN": "សួនច្បារ", + "GATE": "ទ្វារ", + "GREENHOUSE": "ផ្ទះកញ្ចក់", + "HIDE_ALL": "លាក់ទាំងអស់", + "LABEL": "ស្លាកសញ្ញា", + "LINES": "ខ្សែបន្ទាត់", + "NA": "តំបន់ធម្មជាតិ", + "NATURAL_AREA": "តំបន់ធម្មជាតិ", + "POINTS": "ចំណុច", + "RESIDENCE": "លំនៅឋាន", + "SATELLITE": "ផ្ទៃខាងក្រោយផ្កាយរណប", + "SENSOR": "ឧបករណ៍ចាប់សញ្ញា​ / សេនស័រ", + "SENSOR_ARRAY": "សំណុំឧបករណ៍ចាប់សញ្ញា/សិនស័រ", + "SHOW_ALL": "បង្ហាញទាំងអស់", + "SOIL_SAMPLE_LOCATION": "ទីតាំងយកសំណាកដី", + "SURFACE_WATER": "ផ្ទៃខាងលើទឹក", + "TITLE": "តម្រងទៅកាន់ផែនទីរបស់អ្នក", + "WATER_VALVE": "វ៉ាល់ទឹក", + "WATERCOURSE": "ផ្លូវទឹក", + "WV": "វ៉ាល់ទឹក" + }, + "NATURAL_AREA": { + "EDIT_TITLE": "កែតំបន់ធម្មជាតិ", + "NAME": "ឈ្មោះតំបន់ធម្មជាតិ", + "TITLE": "បន្ថែមតំបន់ធម្មជាតិ" + }, + "NOTES_CHAR_LIMIT": "កំណត់ចំណាំត្រូវមានតិចជាង 10.000 តួអក្សរ", + "RESIDENCE": { + "EDIT_TITLE": "កែទីលំនៅ", + "NAME": "ឈ្មោះទីលំនៅ", + "TITLE": "បន្ថែមទីលំនៅ" + }, + "SOIL_SAMPLE_LOCATION": { + "EDIT_TITLE": "កែទីតាំងយកសំណាកដី", + "LATITUDE": "រយៈទទឹង", + "LONGITUDE": "រយៈបណ្ដោយ", + "NAME": "ឈ្មោះទីតាំងយកសំណាកដី", + "TITLE": "បន្ថែមទីតាំងយកសំណាកដី" + }, + "SPOTLIGHT": { + "ADD": "បន្ថែមទីតាំងទៅលើផែនទីរបស់អ្នក", + "ADD_TITLE": "បន្ថែមទៅលើផែនទីរបស់អ្នក", + "EXPORT": "ទាញយក ឬចែករំលែកផែនទីរបស់អ្នក", + "EXPORT_TITLE": "នាំចេញផែនទីរបស់អ្នក", + "FILTER": "ផ្លាស់ប្តូរទីតាំងដែលអ្នកឃើញលើផែនទី", + "FILTER_TITLE": "តម្រងផែនទីរបស់អ្នក", + "HERE_YOU_CAN": "នៅទីនេះ អ្នកអាច៖" + }, + "SURFACE_WATER": { + "EDIT_TITLE": "កែប្រែទឹកផ្ទៃដី", + "IRRIGATION": "តើតំបន់នេះត្រូវបានប្រើសម្រាប់ស្រោចស្រពដែរឬទេ?", + "NAME": "ឈ្មោះប្រភពទឹកលើផ្ទៃដី", + "TITLE": "បន្ថែមផ្ទៃទឹក" + }, + "TAB": { + "CROPS": "ដំណាំ", + "DETAILS": "ព័ត៌មានលំអិត", + "FIELD_TECHNOLOGY": "បច្ចេកវិទ្យាវាល", + "IRRIGATION": "ការស្រោចស្រព", + "TASKS": "កិច្ចការ" + }, + "TITLE": "ផែនទីកសិដ្ឋាន", + "TUTORIAL": { + "ADJUST_AREA": { + "TEXT": "ចុចហើយអូសចំណុចដើម្បីកែសម្រួលតំបន់", + "TITLE": "កែសម្រួលតំបន់" + }, + "ADJUST_LINE": { + "TEXT": "ចុចហើយអូសចំណុចដើម្បីកែសម្រួលបន្ទាត់", + "TITLE": "កែសម្រួលបន្ទាត់" + }, + "AREA": { + "STEP_ONE": "ចុចកន្លែងណាមួយដើម្បីចាប់ផ្តើមគូរ", + "STEP_THREE": "ចុចហើយអូសចំណុចដើម្បីកែសម្រួលរាង", + "STEP_TWO": "ចុចចំណុចដំបូងដើម្បីបិទតំបន់", + "TITLE": "គូរទីតាំង" + }, + "LINE": { + "STEP_FOUR": "(សម្រាប់ប្រភេទបន្ទាត់ខ្លះ) បន្ថែមទទឹង", + "STEP_ONE": "ចុចកន្លែងណាមួយដើម្បីចាប់ផ្តើមគូរ", + "STEP_THREE": "អាចកែសម្រួលបន្ទាត់របស់អ្នកបានតាមចិត្ត", + "STEP_TWO": "ចុចពីរដងដើម្បីបញ្ចប់បន្ទាត់", + "TITLE": "គូរបន្ទាត់" + } + }, + "UNABLE_TO_RETIRE": { + "BODY": "អ្នកអាចដកទីតាំងចេញបានតែពេលដែលគ្មានដំណាំកំពុងដំណើរការ ឬបានគ្រោងទុក គ្មានសត្វ ឬកិច្ចការ។", + "TITLE": "មិនអាចបញ្ឈប់" + }, + "WATER_VALVE": { + "EDIT_TITLE": "កែសន្ទះបិទទឹក", + "GROUNDWATER": "ទឹកក្រោមដី", + "MAX_FLOW_RATE": "អត្រាលំហូរអតិប្បរមា", + "MUNICIPAL_WATER": "ទឹកផ្គត់ផ្គង់ពីក្រុង", + "NAME": "ឈ្មោះសន្ទះបិទទឹក", + "RAIN_WATER": "ទឹកភ្លៀង", + "SURFACE_WATER": "ទឹកលើផ្ទៃដី", + "TITLE": "បន្ថែមសន្ទះបិទទឹក", + "WATER_VALVE_TYPE": "តើប្រភពអ្វី?" + }, + "WATERCOURSE": { + "BUFFER": "តំបន់ទប់ស្កាត់តាមដងទឹក", + "EDIT_TITLE": "កែផ្លូវទឹក", + "IRRIGATION": "តើតំបន់នេះត្រូវបានប្រើសម្រាប់ស្រោចស្រពដែរឬទេ?", + "LENGTH": "ប្រវែងសរុប", + "NAME": "ឈ្មោះផ្លូវទឹក", + "TITLE": "បន្ថែមផ្លូវទឹក", + "WIDTH": "ទទឹងផ្លូវទឹក" + } + }, + "FARM_NOTE": { + "ADD_A_NOTE": "បន្ថែមកំណត់ចំណាំ", + "ATTACH_PHOTO": "ភ្ជាប់រូបថត", + "CANCEL": "បោះបង់", + "COLLAPSE": "បិទកំណត់ចំណាំ", + "DELETE_CONFIRMATION": { + "BODY": "តើអ្នកប្រាកដថាចង់លុបកំណត់ចំណាំនេះមែនទេ? សកម្មភាពនេះមិនអាចត្រឡប់ក្រោយបានទេ។", + "TITLE": "បោះបង់កំណត់ចំណាំ" + }, + "DELETE_NOTE": "បោះបង់កំណត់ចំណាំ", + "EDIT_NOTE": "កែកំណត់ចំណាំ", + "EMPTY_STATE": "អ្នកមិនមានកំណត់ចំណាំទេ", + "EXPIRATION_WARNING": "កំណត់ចំណាំនឹងត្រូវលុបដោយស្វ័យប្រវត្តិបន្ទាប់ពី 30 ថ្ងៃ", + "FARM_NOTES": "កំណត់ចំណាំកសិដ្ឋាន", + "HAS_UNREAD_NOTES": "មានកំណត់ចំណាំមិនទាន់អាន", + "NEW_NOTE": "កំណត់ចំណាំថ្មី", + "NOTE_LABEL": "កំណត់ចំណាំ", + "NOTE_PLACEHOLDER": "វាយបញ្ចូលកំណត់ចំណាំរបស់អ្នក", + "PRIVATE_NOTE": "កំណត់ចំណាំឯកជន", + "SAVE_NOTE": "រក្សាទុកកំណត់ចំណាំ" + }, + "FARM_SETTINGS": { + "TABS": { + "ADDONS": "មុខងារបន្ថែម", + "BASIC_PROFILE": "ព័ត៌មានប្រវត្តិមូលដ្ឋាន", + "MARKET_DIRECTORY": "បញ្ជីទីផ្សារ" + } + }, + "FIELDS": { + "EDIT_FIELD": { + "SUPPLIER": "អ្នកផ្គត់ផ្គង់", + "VARIETY": "ប្រភេទពូជ" + } + }, + "FILE_SIZE_MODAL": { + "BODY": "ឯកសារមិនអាចមានទំហំធំជាង {{size}} មេកាបៃ បានទេ។", + "TITLE": "ទំហំឯកសារធំពេក" + }, + "FILTER": { + "CLEAR": "លុប", + "CLEAR_ALL": "លុបទាំងអស់", + "CLEAR_ALL_FILTERS": "លុបតម្រងទាំងអស់", + "SELECT_ALL": "ជ្រើសរើសទាំងអស់", + "SELECTED_one": "{{count}} បានជ្រើសរើស", + "SELECTED_other": "{{count}} បានជ្រើសរើស", + "SHOWING_ALL": "បង្ហាញទាំងអស់", + "SHOWING_ALL_DEFAULT": "បង្ហាញទាំងអស់ ​(លំនាំដើម)" + }, + "FINANCES": { + "ACTUAL_REVENUE": { + "ADD_REVENUE": "បន្ថែមប្រាក់ចំណូល", + "TITLE": "ប្រាក់ចំណូលជាក់ស្តែង" + }, + "ADD_EXPENSE": "+ បន្ថែមចំណាយ", + "ADD_REVENUE": "+ បន្ថែមចំណូល", + "ADD_TRANSACTION": "+ បន្ថែមប្រតិបត្តិការ", + "CANT_FIND": { + "INFO_EXPENSE": "អ្នកក៏អាចបង្កើតប្រភេទចំណាយផ្ទាល់ខ្លួនរបស់អ្នកបានដែរ!", + "INFO_REVENUE": "អ្នកក៏អាចបង្កើតប្រភេទប្រាក់ចំណូលផ្ទាល់ខ្លួនរបស់អ្នកបានដែរ!", + "MAIN": "មិនអាចរកឃើញប្រភេទដែលសមស្របបានរឺ?", + "MANAGE_EXPENSE": "គ្រប់គ្រងចំណាយផ្ទាល់ខ្លួនរបស់អ្នក", + "MANAGE_REVENUE": "គ្រប់គ្រងចំណូលផ្ទាល់ខ្លួនរបស់អ្នក", + "MISC_EXPENSE": "ឬ <1>បង្កើត<1>ចំណាយផ្សេងៗចំណាយ" + }, + "COST": "តម្លៃ", + "DATE": "កាលបរិច្ឆេទ", + "ESTIMATED_REVENUE": { + "ESTIMATED_ANNUAL_REVENUE": "ប្រាក់ចំណូលប្រចាំឆ្នាំប៉ាន់ស្មាន", + "ESTIMATED_ANNUAL_YIELD": "ការប្រមូលផលប្រចាំឆ្នាំប៉ាន់ស្មាន", + "ESTIMATED_CROP_REVENUE": "ប្រាក់ចំណូលពីដំណាំប៉ាន់ស្មាន", + "ESTIMATED_PRICE_PER_UNIT": "តម្លៃប៉ាន់ស្មានក្នុងមួយឯកតា", + "TITLE": "ប្រាក់ចំណូលប៉ាន់ស្មាន" + }, + "EXPENSES": "ចំណាយ", + "FILTER": { + "EXPENSE_TYPE": "ប្រភេទចំណាយ", + "HELP_TEXT": "សូមប្រើតម្រងខាងក្រោមដោយសេរី ដើម្បីកែសម្រួលបញ្ជីប្រតិបត្តិការរបស់អ្នកឲ្យសមស្របតាមចិត្តអ្នក!", + "REVENUE_TYPE": "ប្រភេទចំណូល", + "TITLE": "តម្រងប្រតិបត្តិការ" + }, + "REPORT": { + "DATES": "កាលបរិច្ឆេទ", + "FILE_TITLE": "របាយការហិរញ្ញវត្ថុ", + "SETTINGS": "កំណត់ការនាំចេញ", + "TRANSACTION": "ប្រតិបត្តិការ", + "TRANSACTIONS": "ប្រតិបត្តិការ" + }, + "REVENUE": "ចំណូល", + "SEARCH": { + "EXPENSE_TYPES": "ស្វែងរកប្រភេទចំណាយ", + "REVENUE_TYPES": "ស្វែងរកប្រភេទចំណូល" + }, + "TRANSACTION": { + "AMOUNT_UNATTRIBUTED": "ចំនួនមិនបានកំណត់ប្រភព", + "ANIMALS": "សត្វ", + "CROPS": "ដំណាំ", + "DAILY_TOTAL": "សរុបប្រចាំថ្ងៃ", + "LABOUR_EXPENSE": "ចំណាយលើកំលាំងពលកម្ម", + "VIEW_AND_EDIT": "ពិនិត្យ និងកែប្រែ", + "VIEW_LABOUR": "ពិនិត្យចំណាយកំលាំងពលកម្ម" + }, + "VIEW_WITHIN_DATE_RANGE": "មើលប្រាក់ចំណូលក្នុងចន្លោះកាលបរិច្ឆេទនេះ", + "WHOLE_FARM_REVENUE": "ចំណូលកសិដ្ឋានទាំងអស់" + }, + "FORM_VALIDATION": { + "OVER_255_CHARS": "អត្ថបទមិនអាចលើស 255 តួអក្សរបានទេ" + }, + "HELP": { + "ATTACHMENT_LABEL": "បញ្ចូលរូបថតអេក្រង់", + "EMAIL": "អុីមែល", + "FEEDBACK_INVITATION": "ស្នើជំនួយ ឬផ្តល់មតិយោបល់", + "MESSAGE_LABEL": "សារ", + "OPTIONS": { + "OTHER": "ផ្សេងទៀត", + "REPORT_BUG": "រាយការណ៍កំហុស", + "REQUEST_FEATURE": "ស្នើលក្ខណៈពិសេស", + "REQUEST_INFO": "ស្នើព័ត៌មាន" + }, + "PREFERRED_CONTACT": "វិធីទំនាក់ទំនងដែលចូលចិត្ត", + "REQUIRED_LABEL": "ផ្នែកដែលត្រូវបំពេញ", + "SEND_US_FEEDBACK": "ផ្ញើមតិយោបល់មកយើង", + "TYPE_SUPPORT_LABEL": "ប្រភេទជំនួយ", + "TYPE_SUPPORT_PLACEHOLDER": "ជ្រើសរើសប្រភេទជំនួយ", + "WHATSAPP": "កម្មវិធីវ៉ាត់សាប", + "WHATSAPP_NUMBER_LABEL": "លេខកម្មវិធីវ៉ាត់សាប" + }, + "HOME": { + "GREETING": "ថ្ងៃល្អ​ " + }, + "HOVERPILL": { + "PLUS_OTHERS_COUNT_one": "+ {{count}} ផ្សេងទៀត", + "PLUS_OTHERS_COUNT_many": "{{count}} ផ្សេងទៀត", + "PLUS_OTHERS_COUNT_other": "+ {{count}} ផ្សេងទៀត" + }, + "IMAGE_LIGHTBOX": { + "ESC_TO_CLOSE": "ឬចុច “Esc” ដើម្បីបិទ" + }, + "IMAGE_UPLOAD_CAPTURE": { + "PHOTO_LIBRARY": "បណ្ណាល័យរូបថត", + "TAKE_PHOTO": "ថតរូប" + }, + "INSIGHTS": { + "BIODIVERSITY": { + "AMPHIBIANS": "សត្វរស់នៅទឹក និងដី", + "API_OFFSET_LIMIT_ERROR_MESSAGE": "មានការសង្កេតជីវចម្រុះច្រើនពេកនៅក្នុងព្រំដែនកសិដ្ឋានរបស់អ្នក ដើម្បីរាយការណ៍បានត្រឹមត្រូវ សូមបន្ថយទំហំព្រំដែនកសិដ្ឋានរបស់អ្នក ហើយព្យាយាមម្ដងទៀត។", + "BIRDS": "បក្សី", + "CROP_VARIETIES": "ប្រភេទពូជដំណាំ", + "ERROR_TITLE": "មានបញ្ហា", + "GENERIC_ERROR_MESSAGE": "ឡៃហ្វាម បង្កើតការយល់ដឹងអំពីជីវចម្រុះដោយផ្អែកលើប្រភពជាច្រើន ហើយនៅពេលនេះមិនអាចដំណើរការបានទេ។ សូមព្យាយាមម្ដងទៀតនៅពេលក្រោយ។", + "HEADER": "ចំនួនប្រភេទ", + "INFO": "ជីវចម្រុះមានអត្ថប្រយោជន៍ខ្លាំងសម្រាប់មនុស្ស និងភពផែនដី។ យើងគណនាភាពសម្បូរបែបនៃប្រភេទជីវិត ដោយផ្អែកលើកំណត់ត្រាទាំងអស់នៃជីវចម្រុះដែលបានទទួលស្គាល់នៅក្នុងព្រំដែនកសិដ្ឋាន(ទាំងឡាយ)របស់អ្នក។ អ្នកអាចបង្កើនជីវចម្រុះនៃដំណាំនៅលើកសិដ្ឋានរបស់អ្នក ដោយដាំពូជថ្មីៗ។ អ្នកក៏អាចបង្កើនចំនួនជីវចម្រុះក្រៅដំណាំនៅលើកសិដ្ឋានរបស់អ្នក ដោយកត់ត្រាការមើលឃើញតាមរយៈ https://inaturalist.org/app", + "INSECTS": "សត្វល្អិត", + "LOADING": { + "BODY": "យើងកំពុងបង្កើតព័ត៌មានវិភាគថ្មីបំផុតអំពីជីវចម្រុះសម្រាប់កសិដ្ឋានរបស់អ្នក។ ដំណើរការនេះអាចចំណាយពេលរហូតដល់ 60 វិនាទី។", + "TITLE": "កំពុងបង្កើតព័ត៌មានវិភាគថ្មីបំផុតអំពីជីវចម្រុះ..." + }, + "MAMMALS": "ថនិកសត្វ", + "PLANTS": "រុក្ខជាតិ", + "SPECIES_COUNT_one": "{{count}}​ ប្រភេទពូជ", + "SPECIES_COUNT_other": "{{count}}​ ប្រភេទពូជ", + "TITLE": "ជីវចំរុះ" + }, + "CLICK_TO_CALCULATE": "ចុចដើម្បីគណនា", + "CURRENT": "បច្ចុប្បន្ន", + "INFO": "ការវិភាគផ្តល់ព័ត៌មានបន្ថែមអំពីអ្វីកំពុងកើតឡើងនៅលើកសិដ្ឋានរបស់អ្នក។ ទិន្នន័យដែលអ្នកផ្តល់ក្នុងកម្មវិធីកាន់តែច្រើន នោះការវិភាគក៏អាចបង្កើតបានកាន់តែច្រើនផងដែរ។ សូមមើលការវិភាគនីមួយៗសម្រាប់ព័ត៌មានលម្អិតបន្ថែម។", + "LABOUR_HAPPINESS": { + "HEADER": "កិច្ចការ", + "INFO": "ឡៃហ្វាម ប៉ាន់ស្មានកម្រិតសុភមង្គលការងារ ដោយគណនាមធ្យមភាគនៃពិន្ទុការពេញចិត្តដែលបុគ្គលម្នាក់ៗបញ្ចូល នៅពេលពួកគេចុចបញ្ចប់ភារកិច្ចមួយ។", + "TITLE": "សុភមង្គលការងារ" + }, + "PRICES": { + "INFO": "យើងបង្ហាញអ្នកពីទិសដៅនៃតម្លៃលក់របស់អ្នក ប្រៀបធៀបនឹងតម្លៃលក់នៃទំនិញដូចគ្នា នៅក្នុងចម្ងាយដែលបានកំណត់ជុំវិញអ្នក ដែលបានប្រមូលទិន្នន័យពីបណ្តាញ ឡៃហ្វាម ទាំងមូល។", + "NEARBY_FARMS_one": "តម្លៃបណ្តាញផ្អែកលើកសិដ្ឋានចំនួន {{count}} នៅក្នុងតំបន់មូលដ្ឋានរបស់អ្នក", + "NEARBY_FARMS_other": "តម្លៃបណ្តាញផ្អែកលើកសិដ្ឋានចំនួន {{count}} នៅក្នុងតំបន់មូលដ្ឋានរបស់អ្នក", + "NETWORK_PRICE": "តំម្លៃបណ្តាញ", + "NO_ADDRESS": "បច្ចុប្បន្នអ្នកមិនទាន់បានបញ្ចូលអាសយដ្ឋានក្នុង ឡៃហ្វាម ទេ។ សូមធ្វើបច្ចុប្បន្នភាពអាសយដ្ឋាននៅក្នុង ប្រវត្តិរូប របស់អ្នក ដើម្បីទទួលបានព័ត៌មានតម្លៃនៅជិតតំបន់របស់អ្នក!", + "OWN_PRICE": "តម្លៃផ្ទាល់ខ្លួន", + "PERCENT_OF_MARKET": "{{percentage}}% នៃទីផ្សារ", + "SALES_FROM_DISTANCE_AWAY": "ការលក់ពីចម្ងាយ {{distance}} {{unit}} ចេញពីទីតាំងរបស់អ្នក", + "TITLE": "តម្លៃ", + "Y_TITLE": "តម្លៃ ({{currency}}{{mass}})" + }, + "SOIL_OM": { + "ALTERNATE_TITLE": "បរិមាណសារធាតុអង្គធាតុសរីរាង្គក្នុងដី", + "HEADER": "សារធាតុសរីរាង្គក្នុងដី", + "INFO": "សារធាតុអង្គធាតុសរីរាង្គក្នុងដី គឺចាំបាច់សម្រាប់រក្សាបរិស្ថានដីឲ្យមានសុខភាពល្អសម្រាប់ដំណាំរបស់អ្នក។ យើងបំពេញព័ត៌មានវិភាគនេះដោយផ្អែកលើលទ្ធផលពីការវិភាគដីចុងក្រោយបំផុតរបស់អ្នក។ ប្រសិនបើអ្នកមិនមានទិន្នន័យណាមួយទេ យើងនឹងប៉ាន់ស្មានបរិមាណសារធាតុអង្គធាតុសរីរាង្គក្នុងដីដែលអាចមាននៅទីតាំងរបស់អ្នកនៅទូទាំងពិភពលោក។", + "TITLE": "សារធាតុសរីរាង្គក្នុងដី" + }, + "TAPE": { + "COMPLETED": "បានបញ្ចប់ - មើលលទ្ធផលរបស់អ្នក", + "IN_PROGRESS": "កំពុងដំណើរការ", + "LOAD_ERROR": "មិនអាចផ្ទុកការស្ទង់មតិបានទេ។ សូមព្យាយាមម្តងទៀតពេលក្រោយ។", + "NOT_FILLED": "មិនទាន់បំពេញ", + "RESULTS_LOAD_ERROR": "មិនអាចផ្ទុកលទ្ធផលបានទេ។ សូមព្យាយាមម្តងទៀតពេលក្រោយ។", + "RESULTS_TITLE": "ពិន្ទុការចាត់ថ្នាក់នៃការផ្លាស់ប្តូរអេកូឡូស៊ីកសិកម្ម​ (CAET)", + "TITLE": "ការស្ទង់មតិ TAPE (ឧបករណ៍វាយតម្លៃសមត្ថភាពកសិកម្មអេកូឡូស៊ី)", + "UPDATE_ANSWERS": "ធ្វើបច្ចុប្បន្នភាពចម្លើយរបស់អ្នក" + }, + "TITLE": "ការវិភាគ", + "UNAVAILABLE": "មិនអាចរកបាន" + }, + "INTRODUCE_MAP": { + "BODY": "ផែនទីកសិដ្ឋានមានមុខងារថ្មីៗបន្ថែម។ ឥឡូវនេះវាត្រូវបានរកឃើញនៅក្រោមតារាងកសិដ្ឋានរបស់ខ្ញុំ។", + "TITLE": "យើងបានធ្វើបច្ចុប្បន្នភាពផែនទីកសិដ្ឋានហើយ!" + }, + "INVENTORY": { + "PRODUCT_NAME": "ឈ្មោះផលិតផល", + "PRODUCT_TYPE": "ប្រភេទផលិតផល", + "REMOVE_CONFIRMATION": { + "BODY": "តើអ្នកប្រាកដថាចង់លុបផលិតផល {{name}} ចេញពីបញ្ជីសារពើភណ្ឌមែនទេ?", + "TITLE": "លុបផលិតផលចេញពីបញ្ជីសារពើភណ្ឌមែនទេ?" + }, + "SOIL_AMENDMENT": "ការកែប្រែដី", + "UNABLE_TO_REMOVE": { + "BODY": "ផលិតផលនេះត្រូវបានប្រើប្រាស់ក្នុងកិច្ចការដែលបានគ្រោងទុក។ មានកិច្ចការកែលម្អដីយ៉ាងហោចណាស់មួយ ដែលបានកំណត់ពេលប្រើប្រាស់ “{{name}}”។", + "TITLE": "មិនអាចលុបបាន" + } + }, + "INVITATION": { + "BIRTH_YEAR": "ឆ្នាំកំណើត", + "BIRTH_YEAR_ERROR": "ឆ្នាំកំណើតត្រូវស្ថិតនៅចន្លោះពីឆ្នាំ 1900 ដល់", + "BIRTH_YEAR_TOOLTIP": "ព័ត៌មានអាយុត្រូវបានប្រមូលសម្រាប់គោលបំណងស្រាវជ្រាវតែប៉ុណ្ណោះ ហើយនឹងត្រូវចែករំលែកដោយបានដកចេញព័ត៌មានដែលអាចកំណត់អត្តសញ្ញាណបុគ្គលរួចហើយ", + "CREATE_ACCOUNT": "បង្កើតគណនីថ្មី", + "CREATE_NEW_ACCOUNT": "បង្កើតគណនីថ្មី", + "EMAIL": "អុីមែល", + "FULL_NAME": "ឈ្មោះពេញ", + "GENDER": "យេនឌ័រ / ភេទ", + "GENDER_TOOLTIP": "ព័ត៌មានអំពីភេទត្រូវបានប្រមូលសម្រាប់គោលបំណងស្រាវជ្រាវតែប៉ុណ្ណោះ ហើយនឹងត្រូវចែករំលែកដោយបានដកចេញព័ត៌មានដែលអាចកំណត់អត្តសញ្ញាណបុគ្គលរួចហើយ", + "PASSWORD": "លេខកូដសម្ងាត់", + "YOUR_INFORMATION": "ព័ត៌មានរបស់អ្នក" + }, + "INVITE_SIGN_UP": { + "ERROR0": "អ្នកត្រូវការអ្នកប្រើប្រាស់", + "ERROR1": "ដើម្បីទទួលយកការអញ្ជើញចូលរួមកសិដ្ឋាននេះ។", + "HOW_TO_CREATE": "តើអ្នកចង់បង្កើតគណនីថ្មីរបស់អ្នកដោយរបៀបណា?", + "LITEFARM_ACCOUNT": "បង្កើតគណនី ឡៃហ្វាម", + "SIGN_IN_WITH": "ចូលប្រព័ន្ធដោយប្រើ", + "TITLE": "បង្កើតគណនីរបស់អ្នក" + }, + "INVITE_USER": { + "ALREADY_EXISTING_EMAIL_ERROR": "អ្នកប្រើប្រាស់ដែលមានអ៊ីមែលនេះបានមានសិទ្ធិចូលប្រើកសិដ្ឋាននេះរួចហើយ", + "BIRTH_YEAR": "ឆ្នាំកំណើត", + "BIRTH_YEAR_ERROR": "ឆ្នាំកំណើតត្រូវស្ថិតនៅចន្លោះពីឆ្នាំ 1900 ដល់", + "BIRTH_YEAR_TOOLTIP": "ព័ត៌មានអាយុត្រូវបានប្រមូលសម្រាប់គោលបំណងស្រាវជ្រាវតែប៉ុណ្ណោះ ហើយនឹងត្រូវចែករំលែកដោយបានដកចេញព័ត៌មានដែលអាចកំណត់អត្តសញ្ញាណបុគ្គលរួចហើយ", + "CHOOSE_ROLE": "ជ្រើសរើសតួនាទី", + "DEFAULT_LANGUAGE": "អង់គ្លេស", + "DEFAULT_LANGUAGE_VALUE": "km", + "EMAIL": "អុីមែល", + "EMAIL_INFO": "អ្នកប្រើប្រាស់ដែលគ្មានអ៊ីមែល នឹងមិនអាចចូលប្រព័ន្ធបានទេ", + "FULL_NAME": "ឈ្មោះពេញ", + "GENDER": "យេនឌ័រ", + "GENDER_TOOLTIP": "ព័ត៌មានអំពីភេទត្រូវបានប្រមូលសម្រាប់គោលបំណងស្រាវជ្រាវតែប៉ុណ្ណោះ ហើយនឹងត្រូវចែករំលែកដោយបានដកចេញព័ត៌មានដែលអាចកំណត់អត្តសញ្ញាណបុគ្គលរួចហើយ", + "INVALID_EMAIL_ERROR": "សូមបញ្ចូលអ៊ីមែលដែលមានសុពលភាព", + "INVITE": "អញ្ជើញ", + "LANGUAGE_OF_INVITE": "ភាសានៃការអញ្ជើញ", + "PHONE": "ទូរស័ព្ទ", + "PHONE_ERROR": "សូមបញ្ចូលលេខទូរស័ព្ទដែលមានសុពលភាព", + "ROLE": "តួនាទី", + "TITLE": "អញ្ជើញអ្នកប្រើប្រាស់", + "WAGE": "ប្រាក់ឈ្នួលប្រចាំម៉ោង", + "WAGE_ERROR": "ប្រាក់ឈ្នួលត្រូវតែមានសុពលភាព និងមិនជាលេខទសភាគអវិជ្ជមាន", + "WAGE_RANGE_ERROR": "ប្រាក់បៀវត្សត្រូវតែជាលេខវិជ្ជមាន និងតិចជាង 999.999.999" + }, + "IRRIGATION_PRESCRIPTION": { + "APPLICATION_DEPTH": "កម្រិតជម្រៅនៃការប្រើ", + "APPROVE_AND_CREATE_TASK": "តាមរយៈការយល់ព្រមនេះ អ្នកនឹងបង្កើតកិច្ចការស្រោចស្រពមួយ", + "AVAILABLE_SOIL_MOISTURE": "សំណើមដីដែលអាចស្រូបយកបាន", + "DATA_FROM": "ទិន្នន័យពី", + "ESTIMATED_WATER_CONSUMPTION": "ការប្រើប្រាស់ទឹកប៉ាន់ស្មាន", + "ET_RATE": "អត្រាការហួតនិងការបញ្ចេញចំហាយទឹក", + "FULL_IRRIGATION_REPORT": "ស្វែងរករបាយការណ៍ស្រោចស្រពទាំងស្រុងនៅទីនេះ", + "IRRIGATION_PRESCRIPTION_FILES": "ឯកសារក្បួនខ្នាតការស្រោចស្រព", + "IRRIGATION_PRESCRIPTIONS": "ក្បួនខ្នាតការស្រោចស្រព", + "IRRIGATION_ZONE": "តំបន់ស្រោចស្រព", + "PRESCRIPTION_DATE": "កាលបរិច្ឆេទកំណត់", + "SOIL_MOISTURE_DEFICIT": "កង្វះសំណើមដី", + "START_DATE": "កាលបរិច្ឆេទចាប់ផ្តើម", + "START_TIME": "ម៉ោងចាប់បើផ្តើម", + "TASK_STATUS": "ស្ថានភាពកិច្ចការ", + "TITLE": "ក្បួនខ្នាតការស្រោចស្រព", + "ZONE": "តំបន់" + }, + "JOIN_FARM_SUCCESS": { + "IMPORTANT_THINGS": "សូមឲ្យយើងបង្ហាញអ្នកនូវចំណុចសំខាន់ៗមួយចំនួន!", + "SUCCESSFULLY_JOINED": "អ្នកបានចូលរួមដោយជោគជ័យ" + }, + "LOCATION_CREATION": { + "CREATE_BUTTON": "បង្កើតទីតាំង", + "CROP_PLAN_BODY": "អ្នកត្រូវមាន ទីវាលដី​ សួន ផ្ទះកញ្ចក់ ឬ តំបន់ការពារ មុននឹងអាចបញ្ចប់ផែនការដំណាំនេះបាន។ តើអ្នកចង់បង្កើតមួយឥឡូវនេះទេ?", + "GO_BACK_BUTTON": "ត្រឡប់ក្រោយ", + "TASK_BODY": "អ្នកត្រូវមានទីតាំងយ៉ាងហោចណាស់មួយ មុននឹងអាចបង្កើតភារកិច្ចបាន។ តើអ្នកចង់បង្កើតទីតាំងឥឡូវនេះទេ?", + "TASK_BODY_WORKER": "អ្នកត្រូវមានការគ្រប់គ្រងបង្កើតទីតាំងយ៉ាងហោចណាស់មួយ មុននឹងអាចបង្កើតភារកិច្ចបាន។", + "TASK_TITLE": "មិនមានទីតាំងសម្រាប់ភារកិច្ចទេ", + "TITLE": "រកមិនឃើញទីតាំងណាមួយទេ!" + }, + "LOCATION_CROPS": { + "ACTIVE_CROPS": "ដំណាំកំពុងដំណើរការ", + "ADD_NEW": "បន្ថែមដំណាំ", + "INPUT_PLACEHOLDER": "វាយអត្ថបទដើម្បីស្វែងរក", + "PAST_CROPS": "ដំណាំអតីតកាល", + "PLANNED_CROPS": "ដំណាំដែលបានគ្រោងទុក" + }, + "LOG_COMMON": { + "ADD_A_LOG": "បន្ថែមកំណត់ត្រា", + "DELETE_CONFIRMATION": "តើអ្នកពិតជាចង់លុបកំណត់ត្រានេះមែនទេ?", + "EDIT_A_LOG": "កែសម្រួលកំណត់ត្រា", + "FROM": "ពី", + "LOCATION": "ទីតាំង", + "NOTES": "ចំណាំ", + "QUANTITY": "បរិមាណ", + "SELECT_LOCATION": "ជ្រើសរើស", + "TO": "ទៅ" + }, + "LOG_DETAIL": { + "NO": "ទេ", + "YES": "បាទ​ / ចាស" + }, + "LOG_HARVEST": { + "ADD_CUSTOM_HARVEST_USE": "បន្ថែមការប្រើប្រាស់ការប្រមូលផលផ្ទាល់ខ្លួន", + "CROP": "ដំណាំ", + "CROP_PLACEHOLDER": "ជ្រើសរើសដំណាំ", + "CUSTOM_HARVEST_USE": "ការប្រើប្រាស់ការប្រមូលផលផ្ទាល់ខ្លួន", + "HARVEST_ALLOCATION_SUBTITLE": "តើប្រហែលប៉ុន្មាននៃការប្រមូលផលនឹងត្រូវបានប្រើសម្រាប់គោលបំណងនីមួយៗ?", + "HARVEST_ALLOCATION_SUBTITLE_TWO": "ចំនួនដែលត្រូវបែងចែក", + "HARVEST_USE_TYPE_SUBTITLE": "តើការប្រមូលផលនឹងត្រូវបានប្រើប្រាស់យ៉ាងដូចម្តេច?", + "QUANTITY_ERROR": "បរិមាណមិនអាចមានលើសពី 2 ខ្ទង់ទសភាគទេ", + "TITLE": "កំណត់ត្រាប្រមូលផល" + }, + "MANAGEMENT_DETAIL": { + "ABANDON_PLAN": "បោះបង់", + "ADD_A_TASK": "បន្ថែមភារកិច្ច", + "DETAILS": "ព័ត៌មានលម្អិត", + "TASKS": "ភារកិច្ច" + }, + "MANAGEMENT_PLAN": { + "ABANDON": { + "CANT_ABANDON_COMPLETED": "មិនអាចបោះបង់ផែនការដំណាំបានទេ", + "CANT_ABANDON_CONCURRENT_USER": "អ្នកប្រើប្រាស់ផ្សេងបានបញ្ចប់ផែនការនេះហើយ។ សូមត្រឡប់ទៅវិញ ដើម្បីមើលស្ថានភាពផែនការចុងក្រោយបំផុត។" + }, + "ABANDON_MANAGEMENT_PLAN_CONTENT": "ការបោះបង់ផែនការដំណាំនេះ នឹងបោះបង់ភារកិច្ចដែលមិនទាន់បានបញ្ចប់ទាំងអស់ដែលភ្ជាប់ជាមួយវា ហើយនឹងលុបវាចេញពីផែនទីកសិដ្ឋានរបស់អ្នក។", + "ABANDON_MANAGEMENT_PLAN_TITLE": "បោះបង់ផែនការដំណាំមែនទេ?", + "ADD_MANAGEMENT_PLAN": "បន្ថែមផែនការដំណាំ", + "AGE": "អាយុ", + "AS_COVER_CROP": "ជាដំណាំគ្របដណ្តប់ដី", + "ASSIGN_ALL_TASKS": "ភារកិច្ចទាំងអស់ដែលបានបង្កើតពីផែនការដំណាំនេះ នឹងត្រូវកំណត់ទៅឲ្យបុគ្គលនេះ។ អ្នកអាចកែប្រែការកំណត់នេះបាននៅពេលក្រោយ", + "BEDS": "រង", + "BROADCAST": "បាចគ្រាប់ ឬ ដាំជាជួរ", + "COMPLETE_PLAN": { + "ABANDON_DATE": "កាលបរិច្ឆេទបោះបង់", + "ABANDON_NOTES": "កំណត់ចំណាំការបោះបង់", + "ABANDON_PLAN": "ផែនការការបោះបង់", + "ABANDON_REASON": "ហេតុផលការបោះបង់", + "CANT_COMPLETE_ABANDONED": "មិនអាចបញ្ចប់ផែនការដំណាំបានទេ", + "CANT_COMPLETE_CONCURRENT_USER": "អ្នកប្រើប្រាស់ផ្សេងបានបោះបង់ផែនការនេះហើយ។ សូមត្រឡប់ទៅវិញ ដើម្បីមើលស្ថានភាពចុងក្រោយបំផុតនៃផែនការដំណាំ។", + "COMPLETE_DATE": "កាលបរិច្ឆេទបញ្ចប់", + "COMPLETE_PLAN": "បញ្ចប់ផែនការ", + "DATE_OF_CHANGE": "កាលបរិច្ឆេទផ្លាស់ប្តូរស្ថានភាព", + "FUTURE_DATE_INVALID": "អាចមិនស្ថិតនៅអនាគត", + "NOTES_CHAR_LIMIT": "កំណត់ចំណាំត្រូវមានតិចជាង 10.000 តួអក្សរ", + "RATING": "វាយតម្លៃផែនការដំណាំនេះ", + "REASON": { + "CROP_FAILURE": "បរាជ័យនៃដំណាំ", + "LABOUR_ISSUE": "បញ្ហាកម្លាំងពលកម្ម", + "MACHINERY_ISSUE": "បញ្ហាម៉ាស៊ីន", + "MARKET_PROBLEM": "បញ្ហាទីផ្សារ", + "SCHEDULING_ISSUE": "បញ្ហាកាលវិភាគ", + "SOMETHING_ELSE": "អ្វីមួយផ្សេងទៀត", + "WEATHER": "អាកាសធាតុ" + }, + "WHAT_HAPPENED": "មានអ្វីកើតឡើង?" + }, + "COMPLETION_NOTES": "កំណត់ចំណាំបញ្ចប់", + "CONTAINER": "ធុង", + "CONTAINER_OR_IN_GROUND": "តើអ្នកកំពុងដាំក្នុងធុង ឬដាំលើដីផ្ទាល់?", + "CONTAINER_TYPE": "ប្រភេទធុង", + "COVER_INFO": "ការជ្រើសរើសដំណាំគ្របដណ្តប់ នឹងបង្កើតភារកិច្ចការងារកសិកម្ម ដើម្បីបញ្ចប់ដំណាំគ្របដណ្តប់នៅចុងរដូវ។ ការជ្រើសរើសសម្រាប់ប្រមូលផល នឹងបង្កើតភារកិច្ចប្រមូលផលជំនួសវិញ។", + "COVER_OR_HARVEST": "តើដំណាំនេះកំពុងត្រូវដាំសម្រាប់ជាដំណាំគ្របដណ្តប់ ឬសម្រាប់ប្រមូលផល?", + "CROP_PLAN_REPEAT": "ផែនការដំណាំនេះកំពុងធ្វើឡើងវិញ", + "CROP_PLAN_REPEAT_SUBTEXT": "ការចុច “រក្សាទុក” នឹងរក្សាទុកផែនការដំណាំនេះភ្លាមៗ។ បន្ទាប់មក អ្នកនឹងត្រូវបានស្នើឲ្យពិពណ៌នាអំពីរបៀបដែលវាធ្វើឡើងវិញ។", + "DAYS_FROM_PLANTING": "ចំនួនថ្ងៃពីពេលដាំរហូតដល់៖", + "DAYS_FROM_SEEDING": "ចំនួនថ្ងៃពីគ្រាប់ពូជរហូតដល់៖", + "DAYS_TO_HARVEST": "ចំនួនថ្ងៃពីការដាំស្ទូង រហូតដល់ការប្រមូលផលបន្ទាប់៖", + "DAYS_TO_TERMINATION": "ចំនួនថ្ងៃពីការដាំស្ទូងរហូតដល់ការបញ្ចប់​៖", + "DELETE": { + "CANT_DELETE_ABANDON": "បោះបង់", + "CANT_DELETE_ABANDON_INSTEAD": "តើអ្នកចង់បោះបង់ផែនការដំណាំនេះជំនួសវិញទេ?", + "CANT_DELETE_CONCURRENT_USER": "អ្នកប្រើប្រាស់ម្នាក់ទៀតបានបញ្ចប់ ឬបោះបង់ភារកិច្ចមួយលើផែនការនេះរួចហើយ។ សូមធ្វើការផ្ទុកទំព័រឡើងវិញ ដើម្បីទទួលបានស្ថានភាពថ្មីបំផុត។", + "CANT_DELETE_MODIFIED_PLAN": "មិនអាចលុបផែនការដំណាំបានទេ", + "CONFIRM_DELETION": "បញ្ជាក់ការលុប", + "DELETE_PLAN": "លុបផែនការដំណាំ", + "DELETE_PLAN_MESSAGE": "ផែនការដំណាំនេះ និងភារកិច្ចទាំងអស់របស់វានឹងត្រូវបានលុបចេញពីកសិដ្ឋានរបស់អ្នក។ ប្រសិនបើអ្នកចង់រក្សាទុកកំណត់ត្រានៃផែនការដំណាំនេះ សូមចុច “បោះបង់” ជំនួសវិញ។", + "DELETE_PLAN_QUESTION": "លុបផែនការដំណាំមែនទេ?" + }, + "DETAIL_SPOTLIGHT_CONTENTS": "នៅទីនេះ អ្នកអាចកែសម្រួលព័ត៌មានលម្អិតនៃដំណាំរបស់អ្នកបាន។", + "DETAIL_SPOTLIGHT_TITLE": "ព័ត៌មានលម្អិត", + "DO_YOU_WANT_TO_ABANDON_CONTENT": "តើអ្នកចង់បោះបង់ផែនការនេះមែនទេ?", + "DROP_PIN": "ដាក់សញ្ញាទីតាំង", + "DURATION_TOOLTIP": "ទាំងនេះគឺជាតម្លៃដែលបានណែនាំ។ សូមកែតម្រូវតាមលក្ខខណ្ឌក្នុងតំបន់របស់អ្នក។", + "EDITING_PLAN_WILL_NOT_MODIFY": "ការកែសម្រួលផែនការនេះ នឹងមិនធ្វើឲ្យភារកិច្ចដែលបានកំណត់រួចមានការផ្លាស់ប្តូរទេ។", + "ESTIMATED_SEED": "ការប៉ាន់ប្រមាណគ្រាប់ពូជជាការចាំប៉ាច់", + "ESTIMATED_YIELD": "បរិមាណប្រមូលផលប្រចាំឆ្នាំដែលបានប៉ាន់ស្មាន", + "FIRST_MP_SPOTLIGHT": { + "BODY_PART1": "ឡៃហ្វាម​ បានបង្កើតភារកិច្ចមួយចំនួនដោយផ្អែកលើផែនការរបស់អ្នក។ អ្នកអាចបន្ថែមភារកិច្ចបន្ថែម ឬកំណត់ភារកិច្ចទាំងនោះនៅលើអេក្រង់នេះបាន។", + "BODY_PART2": "ផែនការរបស់អ្នកនឹងចាប់ផ្តើមដំណើរការ នៅពេលអ្នកបញ្ចប់ភារកិច្ចមួយ។", + "TITLE": "អបអរសាទរ! អ្នកបានបង្កើតផែនការដំណាំដំបូងរបស់អ្នកដោយជោគជ័យហើយ!" + }, + "FOR_HARVEST": "សម្រាប់ប្រមូលផល", + "GERMINATION": "ការដុះពន្លក", + "HARVEST": "ការប្រមូលផលដំបូង", + "HARVEST_DATE": "តើអ្នករំពឹងថានឹងមានការប្រមូលផលបន្ទាប់នៅពេលណា?", + "HARVEST_TO_DATE": "បរិមាណប្រមូលផលរហូតមកដល់បច្ចុប្បន្ន", + "HARVEST_TO_DATE_INFO": "បរិមាណប្រមូលផលរហូតមកដល់បច្ចុប្បន្ន ត្រូវបានគណនាផ្អែកលើភារកិច្ចប្រមូលផលដែលបានបញ្ចប់នៅក្នុងផែនការដំណាំនេះ", + "HISTORICAL_CONTAINER_OR_IN_GROUND": "តើវាត្រូវបានដាំក្នុងកុងតឺន័រ ឬដាំលើដីផ្ទាល់?", + "IN_GROUND": "ក្នុងដី", + "INCOMPLETE_TASK_CONTENT": "ផែនការនេះមានភារកិច្ចដែលមិនទាន់បានបញ្ចប់នៅឡើយ។ អ្នកត្រូវកំណត់ភារកិច្ចទាំងនោះថាបានបញ្ចប់ ដើម្បីអាចបញ្ចប់ផែនការដំណាំនេះបាន។", + "INCOMPLETE_TASK_TITLE": "អ្នកមានភារកិច្ចដែលមិនទាន់បានបញ្ចប់", + "INDIVIDUAL_CONTAINER": "ដាច់ដោយឡែក ឬក្នុងធុង", + "IS_TRANSPLANT": "តើដំណាំនេះនឹងត្រូវបានស្ទូង ដែរឬទេ?", + "KNOW_HOW_IS_CROP_PLANTED": "តើអ្នកដឹងថាដំណាំនេះត្រូវបានដាំដោយវិធីណាដែរឬទេ?", + "LOCATION_SUBTEXT": "បង្ហាញតែទីតាំងដែលអាចដាំដំណាំបានប៉ុណ្ណោះ។", + "MANAGEMENT_SPOTLIGHT_1": "បង្កើតផែនការថ្មីសម្រាប់ដំណាំនេះ", + "MANAGEMENT_SPOTLIGHT_2": "មើល និងកែសម្រួលផែនការសម្រាប់ដំណាំនេះ", + "MANAGEMENT_SPOTLIGHT_3": "បង្កើត និងកំណត់ភារកិច្ច", + "MANAGEMENT_SPOTLIGHT_TITLE": "ការគ្រប់គ្រង", + "NEXT_HARVEST": "តើអ្នករំពឹងថានឹងមានការប្រមូលផលបន្ទាប់នៅពេលណា?", + "NOTES_CHAR_LIMIT": "កំណត់ចំណាំត្រូវមានប្រវែងតិចជាង 10.000 តួអក្សរ", + "NUMBER_OF_CONTAINER": "ចំនួនធុង", + "PENDING_TASK": "ភារកិច្ចកំពុងរង់ចាំ", + "PLAN_AND_ID": "ផែនការ {{id}}", + "PLAN_NAME": "ឈ្មោះផែនការដំណាំ", + "PLAN_NOTES": "កំណត់ចំណាំផែនការ", + "PLANT_SPACING": "គំលាតដំណាំ", + "PLANTED_ALREADY": "តើអ្នកនឹងដាំដំណាំនេះ ឬវាត្រូវបានដាំនៅលើដីរួចហើយ?", + "PLANTING": "ការដាំ", + "PLANTING_DATE": "តើកាលបរិច្ឆេទដាំរបស់អ្នកនៅថ្ងៃណា?", + "PLANTING_DATE_INFO": "កាលបរិច្ឆេទបណ្តុះគ្រាប់ពូជ ដោយផ្អែកលើអាយុដំណាំ៖ {{seed_date}}", + "PLANTING_DATE_LABEL": "កាលបរិច្ឆេទការដាំ", + "PLANTING_DEPTH": "ជំរៅការដាំ", + "PLANTING_METHOD": "តើវិធីសាស្ត្រដាំរបស់អ្នកជាអ្វី?", + "PLANTING_METHOD_TOOLTIP": "ការជ្រើសរើសវិធីសាស្ត្រដាំដែលត្រឹមត្រូវ នឹងជួយឲ្យ ឡែហ្វាម ប៉ាន់ស្មានបរិមាណគ្រាប់ពូជដែលត្រូវការ ទិន្នផល និងព័ត៌មានមានប្រយោជន៍ផ្សេងៗបានត្រឹមត្រូវជាងមុន។", + "PLANTING_NOTE": "កំណត់ចំណាំការដាំ", + "PLANTING_SOIL": "ដីដែលនឹងត្រូវប្រើសម្រាប់ដាំ", + "PLANTS_PER_CONTAINER": "ចំនួនដំណាំក្នុងមួយធុង", + "RATE_THIS_MANAGEMENT_PLAN": "ការវាយតម្លៃផែនការ", + "REMOVE_PIN": "លុបសញ្ញាទីតាំង", + "REPEATED_MP_SPOTLIGHT": { + "BODY": "អ្នកអាចចុចទីនេះ ដើម្បីមើលផែនការដំណាំទាំងអស់ក្នុងក្រុមនេះ។ ការកែប្រែផែនការដំណាំមួយដោយឡែក នឹងមិនប៉ះពាល់ដល់ផែនការផ្សេងទៀតក្នុងក្រុមទេ។", + "TITLE": "អបអរសាទរ! អ្នកបានបង្កើតផែនការដំណាំឡើងម្តងទៀតជាលើកដំបូងរបស់អ្នកដោយជោគជ័យហើយ!" + }, + "ROW_METHOD": { + "HISTORICAL_SAME_LENGTH": "តើជួរដំណាំទាំងអស់មានប្រវែងដូចគ្នាឬទេ?", + "LENGTH_OF_ROW": "ប្រវែងជួរ", + "NUMBER_OF_ROWS": "ចំនួនជួរ", + "SAME_LENGTH": "តើជួរដំណាំរបស់អ្នកទាំងអស់មានប្រវែងដូចគ្នាឬទេ?", + "TOTAL_LENGTH": "ប្រវែងសរុបនៃជួរដំណាំ" + }, + "ROWS": "ជួរ", + "SEED_DATE": "តើកាលបរិច្ឆេទបណ្តុះគ្រាប់ពូជរបស់អ្នកជាថ្ងៃណា?", + "SEED_OR_SEEDLING": "តើអ្នកនឹងដាំដំណាំនេះដោយវិធីណា?", + "SEEDING_DATE": "កាលបរិច្ឆេទបណ្តុះគ្រាប់ពូជ", + "SEEDLING": "ស្តុកដំណាំ​រឺស្តុកបណ្តុះគ្រាប់", + "SEEDLING_AGE": "អាយុប្រហាក់ប្រហែលនៃកូនដំណាំ ឬស្តុកដំណាំ មានប៉ុន្មាន?", + "SEEDLING_AGE_INFO": "អាយុប្រហាក់ប្រហែលនឹងជួយ ឡៃហ្វាម ក្នុងការប៉ាន់ស្មានកាលបរិច្ឆេទប្រមូលផលសម្រាប់កូនដំណាំ។ សម្រាប់ការកាត់ដាំ និងស្តុកដំណាំផ្សេងៗដែលគ្មានអាយុច្បាស់លាស់ អ្នកអាចបញ្ចូលលេខ 0 បាន។", + "SELECT_A_PLANTING_LOCATION": "ជ្រើសរើសទីតាំងដាំ", + "SELECT_A_SEEDING_LOCATION": "ជ្រើសរើសទីតាំងដាំ", + "SELECT_CURRENT_LOCATION": "ជ្រើសរើសទីតាំងបច្ចុប្បន្នរបស់ដំណាំ", + "SELECTED_STARTING_LOCATION": "សូមជ្រើសរើសទីតាំងនេះជាទីតាំងចាប់ផ្តើមសម្រាប់ដំណាំដែលនឹងត្រូវស្ទូងជានិច្ច", + "SPOTLIGHT_HERE_YOU_CAN": "ទីនេះអ្នកអាច៖", + "STARTED": "តោះចាប់ផ្តើម", + "STATUS": { + "ABANDONED": "បានបោះបង់", + "ACTIVE": "សកម្ម", + "COMPLETED": "បញ្ចប់", + "PLANNED": "មានផែនការ" + }, + "SUPPLIER": "អ្នកផ្គត់ផ្គង់", + "TERMINATION": "ការបញ្ឈប់", + "TERMINATION_DATE": "តើអ្នកនឹងបញ្ឈប់ការដាំដំណាំនេះនៅពេលណា?", + "TOTAL_PLANTS": "ចំនួនរុក្ខជាតិ", + "TRANSPLANT": "ស្ទូង", + "TRANSPLANT_DATE": "តើថ្ងៃស្ទូងដំណាំរបស់អ្នកគឺថ្ងៃណា?", + "TRANSPLANT_LOCATION": "តើអ្នកនឹងស្ទូងដំណាំទៅទីតាំងណា?", + "TRANSPLANT_SPOTLIGHT": { + "BODY": { + "PLANTED": "បានដាំ", + "SEEDED": "បានដាំគ្រាប់ពូជ", + "TEXT": "សូមបញ្ជាក់ទីតាំងដំបូងដែលដំណាំនេះនឹងត្រូវដាំ <1>{{fill}}។ យើងនឹងសួរអំពីទីតាំងដែលអ្នកនឹងស្ទូងវាទៅនៅពេលក្រោយ។" + }, + "TITLE": { + "PLANTING": "ការដាំ", + "SEEDING": "ការបណ្តុះគ្រាប់", + "TEXT": "{{fill}} ទីតាំង" + } + }, + "WHAT_IS_AGE": "តើដំណាំមានអាយុប្រហាក់ប្រហែលប៉ុន្មាន?", + "WHAT_WAS_PLANTING_METHOD": "តើវិធីសាស្ត្រដាំគឺអ្វី?", + "WHAT_WAS_PLANTING_METHOD_INFO": "ការជ្រើសរើសវិធីដាំដែលសមស្រប នឹងជួយ ឡៃហ្វាម ក្នុងការប៉ាន់ប្រមាណបរិមាណគ្រាប់ពូជដែលត្រូវការ ទិន្នផល និងព័ត៌មានមានប្រយោជន៍ផ្សេងៗទៀតបានត្រឹមត្រូវជាងមុន។", + "WHERE_START_LOCATION": "តើទីតាំងចាប់ផ្តើមរបស់អ្នកនៅទីណា?", + "WHERE_TRANSPLANT_LOCATION": "តើអ្នកនឹងស្ទូងដំណាំទៅទីតាំងណា?", + "WILD_CROP": "តើអ្នកកំពុងប្រមូលផលដំណាំព្រៃមែនទេ?" + }, + "MARKET_DIRECTORY": { + "AGREE_WITH_TERMS": "តាមរយៈការចែករំលែកទិន្នន័យរបស់អ្នកជាមួយ {{ partner }} អ្នកយល់ព្រមតាម <3>លក្ខខណ្ឌ ⬈ របស់ពួកគេ", + "COMPLETE_PROFILE": "សូមបំពេញប្រវត្តិរូបរបស់អ្នកនៅខាងក្រោម ដើម្បីចាប់ផ្តើម និងផ្សព្វផ្សាយផលិតផលរបស់អ្នក។ អ្នកគ្រាន់តែបំពេញជំហាននេះតែម្តងគត់។ អ្នកអាចធ្វើបច្ចុប្បន្នភាពទិន្នន័យដែលបានចែករំលែក និងឈប់ចែករំលែកបានគ្រប់ពេលវេលា។", + "CONSENT": { + "ALMOST_READY": "អ្នកជិតរួចរាល់ក្នុងការផ្សព្វផ្សាយហើយ! ប៉ុន្តែដំបូង សូមបំពេញព័ត៌មានដែលខ្វះខាតនៅក្នុងទម្រង់ព័ត៌មានថតឯកសារទីផ្សារនៅខាងលើសិន។", + "CONSENT_TO_SHARE_INFORMATION": "ខ្ញុំយល់ព្រមចែករំលែកព័ត៌មានខាងលើជាមួយបណ្តាញដៃគូដែលគួរឱ្យទុកចិត្ត។ ខ្ញុំអាចដកការយល់ព្រមនេះបានគ្រប់ពេលវេលា។
ការដកការយល់ព្រមនឹងធ្វើឱ្យ ឡៃហ្វាម​​​​​​​ បញ្ឈប់កា​រធ្វើសមកាលកម្មទិន្នន័យ របស់អ្នក។ ព័ត៌មានរបស់អ្នកអាចនឹងនៅតែមានក្នុងបណ្តាញដៃគូដដែល — អ្នកអាចនឹងត្រូវស្នើសុំឱ្យពួកគេលុបចេញដោយផ្ទាល់។", + "I_AGREE": "ខ្ញុំយល់ព្រម", + "SEE_ALL_DATA": "មើលទិន្នន័យទាំងអស់ដែលនឹងត្រូវចែករំលែក", + "TITLE": "ការយល់ព្រម" + }, + "GET_LISTED": "ដាក់កសិដ្ឋានរបស់អ្នកក្នុងបញ្ជីដៃគូដែលគួរឱ្យទុកចិត្ត", + "INFO_FORM": { + "ABOUT": "អំពីកសិដ្ធាន", + "ABOUT_PLACEHOLDER": "ធ្វើការពិពណនាអំពី", + "AT_USERNAME": "@ឈ្មោះអ្នកប្រើប្រាស់", + "COUNTRY_CODE": "លេខកូដប្រទេស", + "EMAIL_ADDRESS": "អាសយដ្ឋានអ៊ីមែល", + "EMAIL_PLACEHOLDER": "អាសយដ្ឋានអ៊ីមែលនៃហាងកសិដ្ឋានរបស់អ្នក", + "FARM_IDENTITY": "អត្តសញ្ញាណកសិដ្ឋាន", + "FARM_LOGO": "និមិត្តសញ្ញាកសិដ្ឋាន", + "FARM_NAME": "ឈ្មោះកសិដ្ឋាន", + "FARM_REPRESENTATIVE": "អ្នកតំណាងកសិដ្ឋាន", + "FARM_STORE_CONTACT": "ព័ត៌មានទំនាក់ទំនងហាងកសិដ្ឋាន", + "FARM_STORE_LOCATION": "ទីតាំងហាងកសិដ្ឋាន", + "INVALID_ADDRESS": "អាសយដ្ឋានមិនត្រឹមត្រូវ", + "INVALID_USERNAME_OR_URL": "ទម្រង់មិនត្រឹមត្រូវសម្រាប់ {{social}}", + "INVALID_WEBSITE": "អាសយដ្ឋានគេហទំព័រមិនត្រឹមត្រូវ", + "ONLINE_PRESENCE": "វត្តមានលើអនឡាញ", + "PHONE_NUMBER": "លេខទូរស័ព្ទ", + "PRIVATE_INFO_NOTE": "ទីវាលឯកជននឹងត្រូវបានចែករំលែកជាមួយដៃគូក្នុងបញ្ជីឈ្មោះ ប៉ុន្តែមិនត្រូវបានផ្សព្វផ្សាយសាធារណៈទេ", + "PRODUCT_CATEGORY": "ប្រភេទផលិតផល", + "SOCIAL_INPUT_LABEL": "ឈ្មោះអ្នកប្រើប្រាស់ {{social}}", + "WEBSITE": "គេហទំព័រ" + }, + "INFO_SUMMARY": { + "FARM_EMAIL": "អ៊ីមែលកសិដ្ឋាន", + "FARM_PROFILE": "ប្រវត្តិរបស់កសិដ្ឋាន", + "FARM_STORE_ADDRESS": "អាសយដ្ឋានហាងកសិដ្ឋាន", + "FIRST_NAME_AND_LAST_NAME": "នាមខ្លួន និង​នាមត្រកូល", + "ONLINE_PRESENCE_ITEM": "គេហទំព័រ អុិនស្តាក្រាម​ ហ្វេសបុក អិច", + "PRODUCTS_AND_SERVICES": "ផលិតផល​និងសេវាកម្ម", + "PRODUCTS_CATEGORIES": "ប្រភេទផលិតផល" + }, + "KNOW_A_MARKETPLACE": "ស្គាល់ទីផ្សារណាមួយដែលយើងគួរគាំទ្រទេ?
សូមចែករំលែកមកយើង។", + "MARKET_DIRECTORIES": "បញ្ជីទីផ្សារ", + "MARKET_DIRECTORY_INFO": "ព័ត៌មានបញ្ជីទីផ្សារ", + "NO_PARTNER": "បច្ចុប្បន្នមិនមានដៃគូនៅទីតាំងរបស់អ្នកទេ។", + "PARTNERS": { + "OFN_DESCRIPTION": "បង្កើតគណនីឥតគិតថ្លៃ ហើយបង្ហោះលើបញ្ជី អូអែហ្វអិន នេះ" + }, + "WHERE_TO_BE_FEATURED": "តើអ្នកចង់បង្ហាញនៅទីណា?" + }, + "MENU": { + "ACTUAL_REVENUES": "ចំណូលជាក់ស្តែង", + "ANIMALS": "សត្វ", + "ANIMALS_GROUPS": "ក្រុម", + "ANIMALS_INVENTORY": "សារពើភ័ណ្ឌ / ស្តុក", + "ANIMALS_LOCATION": "ទីតាំង", + "CERTIFICATIONS": "វិញ្ញាបនបត្រ", + "CROPS": "ដំណាំ", + "DOCUMENTS": "ឯកសារ", + "ESTIMATED_REVENUES": "ចំណូលប៉ាន់ប្រមាណ", + "FARM_SETTINGS": "ការរៀបចំកសិដ្ឋាន", + "FINANCES": "ហិរញ្ញវត្ថុ", + "INSIGHTS": "ទស្សនៈយល់ដឹង", + "INVENTORY": "សារពើភ័ណ្ឌ/ស្តុក", + "LABOUR_EXPENSES": "ចំណាយពលកម្ម", + "MAP": "ផែនទី", + "OTHER_EXPENSES": "ចំណាយផ្សេងៗ", + "PEOPLE": "មនុស្ស/ប្រជាជន", + "TASKS": "ភារកិច្ច", + "TRANSACTION_LIST": "បញ្ជីប្រតិបត្តិការ" + }, + "MY_FARM": { + "CERTIFICATIONS": "វិញ្ញាបនបត្រ", + "FARM_INFO": "ព័ត៌មានកសិដ្ឋាន", + "FARM_MAP": "ផែនទីកសិដ្ឋាន", + "PEOPLE": "មនុស្ស/ប្រជាជន" + }, + "NAVIGATION": { + "SPOTLIGHT": { + "COORDINATE_ACTIVITIES": "សម្របសម្រួលសកម្មភាពកសិកម្ម", + "EDIT_FARM_SETTING": "កែប្រែការកំណត់កសិដ្ឋានរបស់អ្នក", + "FARM_TITLE": "នេះគឺជាប្រវត្តិរូបកសិដ្ឋានរបស់អ្នក", + "INFO": "ព័ត៌មានរបស់អ្នក", + "LOG_OUT": "ប៊ូតុងចាកចេញ", + "MANAGE_EMPLOYEE": "គ្រប់គ្រងបុគ្គលិករបស់អ្នក", + "MANAGE_TASK": "គ្រប់គ្រងភារកិច្ចរបស់អ្នក", + "MAP_FARM": "ធ្វើផែនទីកសិដ្ឋានរបស់អ្នក", + "NOTIFICATION_TITLE": "នេះគឺជាមជ្ឈមណ្ឌលការជូនដំណឹងរបស់អ្នក", + "PROFILE_TITLE": "នេះគឺជាប្រវត្តិរូបរបស់អ្នក", + "SEE_TASK": "មើលអ្វីផ្សេងទៀតដែលកំពុងកើតឡើង", + "SEE_UPDATES": "មើលការធ្វើបច្ចុប្បន្នភាពសំខាន់", + "TASK_TITLE": "នេះគឺជាភារកិច្ចកសិដ្ឋានរបស់អ្នក", + "TIPS": "គន្លឹះមានប្រយោជន៍", + "YOU_CAN": "នៅទីនេះ អ្នកអាច៖", + "YOU_WILL_FIND": "នៅទីនេះ អ្នកនឹងរកឃើញ៖" + } + }, + "NOTIFICATION": { + "DAILY_TASKS_DUE_TODAY": { + "BODY": "អ្នកមានភារកិច្ចដែលត្រូវបញ្ចប់ថ្ងៃនេះ។", + "TITLE": "ភារកិច្ចដែលត្រូវបញ្ចប់ថ្ងៃនេះ" + }, + "NEW_IRRIGATION_PRESCRIPTION": { + "BODY": "ការកំណត់ប្រព័ន្ធស្រោចស្រពថ្មីមួយត្រូវបានបង្កើតឡើង ដោយផ្អែកលើទិន្នន័យអាកាសធាតុ ដី និងដំណាំបច្ចុប្បន្ន សម្រាប់ {{date}}។", + "TITLE": "ក្បួនខ្នាតការស្រោចស្រព{{location}}" + }, + "NONE_TO_DISPLAY": "មិនមានការជូនដំណឹងណាមួយសម្រាប់បង្ហាញទេ។", + "PAGE_TITLE": "ការជូនដំណឹង", + "TAKE_ME_THERE": "នាំខ្ញុំទៅកាន់ទីនោះ", + "TASK_ABANDONED": { + "BODY": "ភារកិច្ច {{taskType}} មួយដែលបានកំណត់ឲ្យអ្នក ត្រូវបានបោះបង់ដោយ {{abandoner}}។", + "TITLE": "ភារកិច្ចដែលត្រូវបានបោះបង់ចោល" + }, + "TASK_ASSIGNED": { + "BODY": "ភារកិច្ច {{taskType}} មួយដែលបានកំណត់ឲ្យអ្នក {{assigner}}។", + "TITLE": "ភារកិច្ចដែលបានកំណត់" + }, + "TASK_COMPLETED_BY_OTHER_USER": { + "BODY": "ភារកិច្ច {{taskType}} មួយដែលបានកំណត់ឲ្យអ្នក ត្រូវបានកំណត់ថាបានបញ្ចប់ដោយ {{assigner}}។", + "TITLE": "ភារកិច្ចបានបញ្ចប់" + }, + "TASK_DELETED": { + "BODY": "ភារកិច្ច {{taskType}} មួយដែលបានកំណត់ឲ្យអ្នក ត្រូវបានលុបដោយ {{abandoner}}។", + "TITLE": "ភារកិច្ចបានលុប" + }, + "TASK_REASSIGNED": { + "BODY": "ភារកិច្ច {{taskType}} មួយដែលបានកំណត់ឲ្យអ្នកមុននេះ ត្រូវបានផ្ទេរទៅឲ្យអ្នកផ្សេងដោយ {{assigner}}។", + "TITLE": "ភារកិច្ច បានកំណត់ឡើងវិញ" + }, + "TASK_RECOMPLETED_BY_OTHER_USER": { + "BODY": "ភារកិច្ច {{taskType}} ដែលបានផ្តល់ឲ្យអ្នក ត្រូវបានកែប្រែ និងបានបញ្ចប់ឡើងវិញដោយ {{assigner}}។", + "TITLE": "ភារកិច្ចបានបញ្ចប់ឡើងវិញ" + }, + "TASK_UNASSIGNED": { + "BODY": "{{editor}} បានកំណត់ភារកិច្ច {{taskType}} មួយថាមិនមានអ្នកទទួលខុសត្រូវទេ។", + "TITLE": "ភារកិច្ចមិនមានអ្នកទទួលខុសត្រូវ" + }, + "TIMELINE": { + "HEADING": "លំដាប់ពេលវេលានៃការជូនដំណឹង", + "MORE_RECENT_NOTIFICATION": "មានការជូនដំណឹងថ្មីជាងនេះទៀតអំពី {{entityType}} នេះ។", + "VIEW_NOW": "មើលឥឡូវនេះ" + }, + "WEEKLY_UNASSIGNED_TASKS": { + "BODY": "អ្នកមានភារកិច្ចដែលមិនទាន់បានកំណត់អ្នកទទួលខុសត្រូវ ហើយត្រូវបញ្ចប់ក្នុងសប្ដាហ៍នេះ។", + "TITLE": "ភារកិច្ចដែលមិនទាន់បានកំណត់អ្នកទទួលខុសត្រូវ" + } + }, + "OFFLINE": { + "ARE_OFFLINE": "អ្នកកំពុងក្រៅបណ្តាញ។ សកម្មភាពមួយចំនួនមិនអាចប្រើបានទេ។", + "BADGE": { + "TITLE": "ក្រៅបណ្តាញ", + "TOOLTIP_CONTENT": "យើងមិនអាចភ្ជាប់ទៅបណ្តាញបាននៅពេលនេះទេ។

អ្នកអាចបន្តនៅក្នុងរបៀបក្រៅបណ្តាញបាន។ ផ្នែកមួយចំនួននឹងអាចមើលបានតែប៉ុណ្ណោះ ប៉ុន្តែផ្នែក កិច្ចការ នៅតែអាចប្រើបានពេញលេញ។" + }, + "CHANGES_WILL_SYNC": "ការផ្លាស់ប្តូរដែលអ្នកធ្វើ នឹងធ្វើសមកាលកម្មវិញនៅពេលអ្នកត្រឡប់មកអនឡាញ។", + "LOG_OUT_MODAL": { + "INFO": "អ្នកនឹងមិនអាចចូលគណនីឡើងវិញនៅពេលក្រៅបណ្តាញបានទេ។ ការផ្លាស់ប្តូរទាំងអស់ដែលបានធ្វើពេលក្រៅបណ្តាញ នឹងត្រូវបាត់បង់បន្ទាប់ពីចាកចេញពីគណនី។", + "TITLE": "តើអ្នកប្រាកដថាចង់ចាកចេញពីគណនីមែនទេ?" + }, + "NOT_READY_BADGE": { + "TITLE": "ព័ត៌មាន", + "TOOLTIP_CONTENT": "ឡែហ្វាម ត្រូវការទាញយកទិន្នន័យ ដើម្បីអាចដំណើរការក្នុងរបៀបក្រៅបណ្តាញបាន។

សូមបញ្ចប់ដំណើរការនេះនៅពេលមានការភ្ជាប់អ៊ីនធឺណិត។" + }, + "NOT_READY_WARNING": "ឡៃហ្វាម មិនទាន់បានរៀបចំទិន្នន័យក្រៅបណ្តាញរួចរាល់ទេ។", + "PREPARE_TO_WORK_OFFLINE": "រៀបចំ ឡៃហ្វាម ដើម្បីអាចដំណើរការក្នុងរបៀបក្រៅបណ្តាញនៅពេលក្រោយ។", + "REFRESH": "ធ្វើឱ្យថ្មី" + }, + "OUTRO": { + "ALL_DONE": "អស្ចារ្យ! អ្នកបានបញ្ចប់ទាំងអស់ហើយ។ ត្រៀមខ្លួនរួចហើយដើម្បីចាប់ផ្តើមធ្វើការងារជាក់ស្តែងហើយមែនទេ?", + "IMPORTANT_THINGS": "ហើយចុងក្រោយ សូមឲ្យយើងបង្ហាញអ្វីសំខាន់ៗពីរបីដល់អ្នក!" + }, + "PASSWORD_RESET": { + "BUTTON": "ផ្ញើតំណ", + "BUTTON_SENDING": "កំពុងបញ្ជូន...", + "DESCRIPTION_BOTTOM": "សូមពិនិត្យអ៊ីមែលរបស់អ្នក។", + "DESCRIPTION_TOP": "តំណភ្ជាប់ត្រូវបានផ្ញើរួចហើយ។", + "LABEL_EMAIL": "អុីមែល", + "LABEL_NEW_PASSWORD": "លេខកូដសម្ងាត់ថ្មី", + "NEW_ACCOUNT_BUTTON": "ធ្វើបច្ចុប្បន្នភាព", + "NEW_ACCOUNT_TITLE": "កំណត់លេខកូដសម្ងាត់ថ្មីរបស់អ្នក", + "TITLE": "តំណភ្ជាប់ត្រូវបានបញ្ជូនរួច" + }, + "PASSWORD_RESET_SUCCESS_MODAL": { + "BUTTON": "ល្អ!", + "DESCRIPTION": "ពាក្យសម្ងាត់របស់អ្នកត្រូវបានធ្វើបច្ចុប្បន្នភាពហើយ។ កំពុងបញ្ជូនអ្នកទៅកាន់កសិដ្ឋានរបស់អ្នកក្នុងរយៈពេល 10 វិនាទី...", + "TITLE": "ជោគជ័យ!" + }, + "PLAN_GUIDANCE": { + "ADDITIONAL_GUIDANCE": "តើអ្នកមានការណែនាំបន្ថែមអ្វីដែលចង់ផ្តល់សម្រាប់ភារកិច្ចបណ្តុះគ្រាប់ពូជនេះទេ?", + "BED": "រង", + "BEDS": "រង", + "NOTES": "កំណត់ចំណាំការដាំ", + "PLANTING_DEPTH": "ជំរៅការដាំ", + "ROW": "ជួរ", + "ROWS": "ជួរ", + "SPACE_BETWEEN": "ចន្លោះរវាង {{types}}", + "SPECIFY": "សូមបញ្ចាក់{{types}}", + "SPECIFY_PLACEHOLDER": "ឧ. {{types}} 1 - 4", + "TOOLTIP": "តួអក្សរ 40 ដំបូងនៃវាលនេះ នឹងត្រូវបង្ហាញនៅគ្រប់ទីកន្លែងដែលផែនការដំណាំរបស់អ្នកត្រូវបានបង្ហាញ។", + "WIDTH": "{{type}} ទទឹង", + "WORD_LIMIT": "អាចបង្ហាញតែ {{limit}} តួអក្សរប៉ុណ្ណោះ" + }, + "PREPARING_EXPORT": { + "MESSAGE": "ឡៃហ្វាម កំពុងរៀបចំឯកសារបញ្ជាក់របស់អ្នកនៅផ្នែកខាងក្រោយ ហើយអ្នកនឹងទទួលអ៊ីមែលនៅពេលរួចរាល់ — វាអាចចំណាយពេលប៉ុន្មាននាទី។ អ្នកអាចចុចក្រៅប្រអប់នេះដើម្បីបន្តប្រើ ឡៃហ្វាម ដោយមិនរំខានដំណើរការនេះ។", + "TITLE": "ការបញ្ចូនព័ត៌មានរបស់អ្នកកំពុងត្រូវបានរៀបចំ" + }, + "PROFILE": { + "ACCOUNT": { + "CONVERT_TO_HAVE_ACCOUNT": "បម្លែងអ្នកធ្វើការនេះទៅជាអ្នកប្រើប្រាស់ដែលមានគណនី", + "EDIT_USER": "កែសម្រួលអ្នកប្រើប្រាស់", + "EMAIL": "អុីមែល", + "FIRST_NAME": "នាមខ្លួន", + "LANGUAGE": "ភាសា", + "LAST_NAME": "នាមត្រកូល", + "PHONE_NUMBER": "លេខទូរស័ព្ទ", + "USER_ADDRESS": "អាស័យដ្ឋាន" + }, + "ACCOUNT_TAB": "គណនី", + "ERROR": { + "FARM_NAME_LENGTH": "ឈ្មោះកសិដ្ឋានមិនអាចលើស 255 តួអក្សរបានទេ", + "FIRST_NAME_LENGTH": "នាមខ្លួនមិនអាចលើស 255 តួអក្សរបានទេ", + "LAST_NAME_LENGTH": "នាមត្រកូលមិនអាចលើស 255 តួអក្សរបានទេ", + "PHONE_NUMBER_LENGTH": "លេខទូរស័ព្ទត្រូវមានតិចជាង 20 តួអក្សរ", + "USER_ADDRESS_LENGTH": "អាសយដ្ឋានអ្នកប្រើប្រាស់មិនអាចលើស 255 តួអក្សរបានទេ" + }, + "FARM": { + "ADDONS": "មុខងារបន្ថែម", + "ADDRESS": "អាសយដ្ឋាន", + "CHANGE_IMAGE": "ប្តូររូបភាព", + "CLICK_TO_UPLOAD": "ចុចដើម្បីបញ្ចូលឡើងទៅ", + "CURRENCY": "រូបិយប័ណ្ណ", + "DRAG_DROP": "ឬអូសទម្លាក់", + "FARM_IMAGE": "រូបភាពកសិដ្ឋាន", + "FARM_NAME": "ឈ្មោះកសិដ្ឋាន", + "IMPERIAL": "ប្រព័ន្ធខ្នាតអ៊ីមភៀររៀល", + "METRIC": "ប្រព័ន្ធខ្នាតម៉ែត្រ", + "PHONE_NUMBER": "លេខទូរស័ព្ទ", + "REMOVE_IMAGE": "លុបរូបភាព", + "UNITS": "ឯកតា", + "UPLOAD_IMAGE": "បញ្ចូលរូបភាព" + }, + "FARM_TAB": "កសិដ្ឋាន", + "PEOPLE": { + "DO_YOU_WANT_TO_REMOVE": "តើអ្នកចង់លុបអ្នកប្រើប្រាស់នេះចេញពីកសិដ្ឋានរបស់អ្នកមែនទេ?", + "INVALID_REVOKE_ACCESS": "មិនអាចដកសិទ្ធិចូលប្រើបានទេ", + "INVITE_USER": "អញ្ជើញអ្នកប្រើប្រាស់", + "LAST_ADMIN_ERROR": "យើងមិនអាចដកសិទ្ធិចូលប្រើរបស់អ្នកប្រើប្រាស់នេះបានទេ ព្រោះគាត់គឺជាអ្នកគ្រប់គ្រងចុងក្រោយនៃកសិដ្ឋាននេះ។ ប្រសិនបើអ្នកចង់លុបកសិដ្ឋានរបស់អ្នក សូមបង្កើតសំណើ ដោយចុច <1>ទីនេះ ជំនួសវិញ។", + "RESTORE_ACCESS": "ស្ដារសិទ្ធិចូលប្រើរបស់អ្នកប្រើប្រាស់", + "REVOKE_ACCESS": "ដកសិទ្ធិចូលប្រើរបស់អ្នកប្រើប្រាស់", + "SEARCH": "ស្វែងរក", + "THIS_WILL_REMOVE": "សកម្មភាពនេះនឹងលុបអ្នកប្រើប្រាស់ចេញពីកសិដ្ឋានរបស់អ្នក។" + }, + "PEOPLE_TAB": "មនុស្ស/ប្រជាជន", + "TABLE": { + "HEADER_EMAIL": "អុីមែល", + "HEADER_NAME": "ឈ្មោះ", + "HEADER_ROLE": "តួនាទី", + "HEADER_STATUS": "ស្ថានភាព" + } + }, + "PROFILE_FLOATER": { + "HELP": "ជួយ", + "INFO": "ព័ត៌មានរបស់ខ្ញុំ", + "LOG_OUT": "ចាកចេញ", + "SWITCH": "ប្ដូរកសិដ្ឋាន", + "TUTORIALS": "មេរៀនណែនាំ" + }, + "REACT_SELECT": { + "CLEAR": "លុប", + "CLEAR_ALL": "លុបទាំងអស់" + }, + "RELEASE": { + "BETTER": "ឡៃហ្វាម កាន់តែប្រសើរជាងមុនហើយ!", + "LITEFARM_UPDATED": "ឡៃហ្វាម វី{{version}} ឥឡូវនេះអាចប្រើបានហើយ!", + "NOTES": "កំណត់សម្គាល់ការចេញផ្សាយ" + }, + "REMOVE_ANIMALS": { + "CREATED_IN_ERROR": "បានបង្កើតកំហុស", + "CULLED": "បានជ្រើសចេញ", + "EXPLANATION": "ការពន្យល់", + "MORE_DETAILS": "តើអ្នកចង់ផ្តល់ព័ត៌មានលម្អិតបន្ថែមទេ?", + "NATURAL_DEATH": "ការស្លាប់តាមធម្មជាតិ", + "REMOVAL_REASONS": "មូលហេតុនៃការដកចេញ", + "REMOVE_ANIMALS": "ដកសត្វចេញ", + "REMOVED_AND_ARCHIVED": "សត្វទាំងនេះត្រូវបានដកចេញពីកសិដ្ឋានរបស់អ្នកដោយជោគជ័យ ហើយនឹងអាចមើលឃើញនៅក្នុងប្រវត្តិសារពើភ័ណ្ឌរបស់អ្នក។", + "SLAUGHTERED_FOR_CONSUMPTION": "បានសម្លាប់សត្វសម្រាប់ការបរិភោគ", + "SLAUGHTERED_FOR_SALE": "បានសម្លាប់សត្វសម្រាប់ការលក់", + "SOLD": "លក់ហើយ", + "WHY": "សូមប្រាប់យើងពីមូលហេតុដែលអ្នកកំពុងដកសត្វទាំងនេះចេញ", + "WILL_BE_ARCHIVED": "សត្វទាំងនេះនឹងត្រូវបានដកចេញពីសារពើភ័ណ្ឌកំពុងប្រើប្រាស់របស់អ្នក", + "WILL_BE_PERMANENTLY_REMOVED": "សត្វទាំងនេះនឹងត្រូវបានដកចេញជាអចិន្ត្រៃយ៍ពីកសិដ្ឋានរបស់អ្នក" + }, + "REPEAT_PLAN": { + "AFTER": "បន្ទាប់ពី", + "COMPLETION": "ការបញ្ចប់", + "CONFIRMATION": { + "AFTER_REPETITIONS": "បន្ទាប់ពីការធ្វើឡើងវិញ <1>{{number}} ដង។", + "BEGINNING": "ការចាប់ផ្តើម", + "CROP_NAME": "ឈ្មោះផែនការដំណាំ", + "FINISHING": "បញ្ចប់", + "HEADER": "បញ្ជាក់ពីរបៀបធ្វើផែនការនេះឡើងវិញ", + "ON_DATE": "នៅថ្ងៃទី​ {{date}}", + "WILL_CREATE": "វានឹងបង្កើត", + "WILL_CREATE_BODY": "<0>{{numberOfPlans}} ផែនការដំណាំថ្មី និង <2>{{numberOfTasks}} ភារកិច្ចថ្មី", + "WILL_REPEAT": "ផែនការនេះនឹងធ្វើឡើងវិញ" + }, + "DUE": "ដល់កំណត់", + "DUPLICATE_NAME": "មានផែនការដំណាំដែលមានឈ្មោះនេះរួចហើយ។ សូមជ្រើសរើសឈ្មោះផ្សេងទៀត។", + "EARLIEST_TASK": "{{date}} គឺជាកាលបរិច្ឆេទ{{dateType}}នៃភារកិច្ចដែលឆាប់បំផុតពីផែនការដើម", + "FINISH": "បញ្ចប់", + "INTERVAL": { + "DAY": "ថ្ងៃ", + "MONTH": "ខែ", + "WEEK": "សប្តាហ៍", + "YEAR": "ឆ្នាំ" + }, + "LATER_DATE_ERROR": "សូមជ្រើសរើសកាលបរិច្ឆេទបន្ទាប់ពីកាលបរិច្ឆេទចាប់ផ្តើម", + "MENU": "ធ្វើផែនការដំណាំឡើងវិញ", + "ON": "បើក", + "PLAN_NAME": "ឈ្មោះផែនការដំណាំកំពុងធ្វើឡើងវិញ", + "REPEAT_EVERY": "ធ្វើឡើងវិញរៀងរាល់", + "REPEAT_LIMIT_ERROR": "មិនអាចធ្វើផែនការនេះឡើងវិញលើសពី 20 ដងបានទេ", + "REPEAT_ON": "ធ្វើម្តងទៀតនៅ", + "REPETITIONS": "ការធ្វើម្តងទៀត", + "REPETITIONS_OF": "ការធ្វើម្តងទៀត​នៃ {{planName}}", + "START_DATE": "ការចាប់ផ្តើម", + "SUBTITLE": "ចម្លងផែនការដំណាំនេះ និងភារកិច្ចទាំងអស់របស់វា តាមកាលវិភាគខាងក្រោម", + "TITLE": "ធ្វើផែនការដំណាំម្តងទៀត" + }, + "REQUEST_CONFIRMATION_MODAL": { + "BUTTON": "យល់ហើយ", + "DESCRIPTION": "នរណាម្នាក់នឹងទាក់ទងអ្នកឆាប់ៗនេះ។", + "TITLE": "សំណើសុំជំនួយត្រូវបានដាក់ស្នើរួចហើយ" + }, + "REVENUE": { + "ADD_REVENUE": { + "ADD_CUSTOM_REVENUE": "បន្ថែមចំណូលផ្ទាល់ខ្លួន", + "CANNOT_BE_CHANGED": "មិនអាចផ្លាស់ប្តូរបានទេ", + "CANNOT_BE_CHANGED_LATER": "មិនអាចផ្លាស់ប្តូរនៅពេលក្រោយបានទេ", + "CROP_GENERATED": "តើចំណូលនេះបានមកពីដំណាំមែនទេ?", + "CUSTOM_REVENUE_NAME": "ឈ្មោះចំណូលផ្ទាល់ខ្លួន", + "CUSTOM_REVENUE_TYPE": "ប្រភេទចំណូលផ្ទាល់ខ្លួន", + "DUPLICATE_NAME": "មានប្រភេទចំណូលដែលមានឈ្មោះនេះរួចហើយ។ សូមជ្រើសរើសឈ្មោះផ្សេង។", + "DUPLICATE_NAME_RETIRED": "មានប្រភេទចំណូលដែលបានដកចេញ ដែលមានឈ្មោះនេះរួចហើយ។ សូមជ្រើសរើសឈ្មោះផ្សេង។", + "ENTITY_ASSOCIATION_LABEL": "តើប្រាក់ចំណូលនេះពាក់ព័ន្ធនឹងសត្វ ឬដំណាំទេ?" + }, + "CUSTOM_REVENUE_DESCRIPTION": "ការពិពណ៌នាចំណូលផ្ទាល់ខ្លួន", + "DELETE": { + "CONFIRM": "បញ្ជាក់ការលុប", + "HEADER": "លុបចំណូលមែនទេ?", + "LINK": "លុបចំណូល", + "MESSAGE": "សកម្មភាពនេះនឹងលុបចំណូលចេញពីកំណត់ត្រាកសិដ្ឋានរបស់អ្នក។ វានឹងមិនបង្ហាញនៅក្នុងសង្ខេបហិរញ្ញវត្ថុណាមួយទៀតទេ។" + }, + "EDIT_REVENUE": { + "RETIRE_REVENUE_MESSAGE": "ការដកចេញប្រភេទចំណូលនេះ នឹងធ្វើឲ្យវាមិនអាចជាជម្រើសសម្រាប់ចំណូលអនាគតបានទៀតទេ។ ប៉ុន្តែអ្នកនៅតែអាចស្វែងរក និងតម្រង់ចំណូលមុនៗដែលមានប្រភេទនេះ នៅក្នុងផ្ទាំងហិរញ្ញវត្ថុបាន។", + "RETIRE_REVENUE_TYPE": "ដកចេញប្រភេទចំណូល", + "RETIRED": "(ដកចេញ)", + "REVENUE_TYPE": "ប្រភេទចំណូល" + } + }, + "REVISION_PROMPT": { + "FIX_IT_NOW": "កែសម្រួលឥឡូវនេះ", + "NOTICED_SOMETHING_OFF": "សង្កេតឃើញមានអ្វីមិនប្រក្រតីមែនទេ?", + "UPDATE_THIS_TASK": "អ្នកអាចត្រឡប់មកពិនិត្យ និងធ្វើបច្ចុប្បន្នភាពព័ត៌មានដែលអ្នកបានដាក់សម្រាប់ភារកិច្ចនេះបាន។" + }, + "ROLE_SELECTION": { + "FARM_EO": "មន្ត្រីផ្សព្វផ្សាយ", + "FARM_MANAGER": "អ្នកគ្រប់គ្រងកសិដ្ឋាន", + "FARM_OWNER": "ម្ចាស់កសិដ្ឋាន", + "IS_OWNER_OPERATED": "តើកសិដ្ឋាននេះត្រូវបានដំណើរការដោយម្ចាស់កសិដ្ឋានមែនទេ?", + "TITLE": "តួនាទីរបស់អ្នកនៅក្នុងកសិដ្ឋានគឺអ្វី?" + }, + "SALE": { + "ADD_SALE": { + "ADD_CUSTOM_REVENUE_TYPE": "បន្ថែមប្រភេទចំណូលផ្ទាល់ខ្លួន", + "ADD_REVENUE": "បន្ថែមចំណូល", + "ANIMAL_NOTES_PLACEHOLDER": "ការពិពណ៌នាការលក់សត្វ", + "COUNT_UNIT_LABEL": "ឯកតា", + "CROP_NOTES_PLACEHOLDER": "ការពិពណ៌នាការលក់ដំណាំ", + "CROP_REQUIRED": "តម្រូវឲ", + "CROP_VARIETY": "ពូជដំណាំ", + "FLOW": "ការបង្កើតចំណូល", + "MANAGE_CUSTOM_REVENUE_TYPE": "គ្រប់គ្រងប្រភេទចំណូលផ្ទាល់ខ្លួន", + "MEASURED_BY": "វាស់ដោយ", + "NOTES_PLACEHOLDER": "ការពិពណ៌នាការលក់", + "SALE_VALUE_ERROR": "តម្លៃការលក់ត្រូវតែជាចំនួនវិជ្ជមាន និងតិចជាង 999.999.999", + "SELECT_CROPS": "ជ្រើសរើសដំណាំ", + "TABLE_HEADERS": { + "TOTAL": "សរុប" + }, + "WHICH_TYPE_TO_RECORD": "សូមជ្រើសរើសប្រភេទចំណូលរបស់អ្នកខាងក្រោម៖" + }, + "DETAIL": { + "CUSTOMER_NAME": "ឈ្មោះអតិថិជន", + "TITLE": "ព័ត៌មានលម្អិតអំពីចំណូល", + "VALUE": "តម្លៃ" + }, + "EDIT_SALE": { + "TITLE": "កែសម្រួលចំណូល" + }, + "EXPENSE_DETAIL": { + "TITLE": "ព័ត៌មានលម្អិតអំពីចំណាយ" + }, + "FINANCES": { + "CARROUSEL_TEXT": { + "ESTIMATED_REVENUE": "លេខនេះ (ថេរ) បង្ហាញពីការប៉ាន់ស្មានទិន្នផលអនាគតរបស់អ្នក", + "GENERIC": "*លេខទាំងនេះផ្អែកលើកាលបរិច្ឆេទរបស់អ្នក / តម្រងជ្រើសរើស" + }, + "ESTIMATED_HARVEST_REVENUE": "ចំណូលប៉ាន់ស្មានពីការប្រមូលផល", + "EXPENSES": "ចំណាយ", + "EXPORT_REPORT": "នាំចេញរបាយការណ៍", + "LABOUR_LABEL": "ពលកម្ម", + "MANAGE_CUSTOM_EXPENSE_TYPES_SPOTLIGHT": { + "BODY": "នៅទីនេះ អ្នកអាចបន្ថែម កែប្រែ ឬបញ្ឈប់ប្រភេទចំណាយដែលត្រូវបានកំណត់ផ្ទាល់ខ្លួនសម្រាប់កសិដ្ឋានរបស់អ្នក។", + "TITLE": "គ្រប់គ្រងប្រភេទចំណាយផ្ទាល់ខ្លួន" + }, + "MANAGE_CUSTOM_REVENUE_TYPES_SPOTLIGHT": { + "BODY": "នៅទីនេះ អ្នកអាចបន្ថែម កែប្រែ ឬបញ្ឈប់ប្រភេទចំណូលដែលត្រូវបានកំណត់ផ្ទាល់ខ្លួនសម្រាប់កសិដ្ឋានរបស់អ្នក។", + "TITLE": "គ្រប់គ្រងប្រភេទចំណូលផ្ទាល់ខ្លួន" + }, + "PROFIT_LOSS": "ចំណេញ​ / ខាត", + "REPORT": "របាយការណ៍", + "REPORT_HELP_TEXT": "តម្រងទាំងនេះស្រដៀងនឹងអ្វីដែលអ្នកឃើញនៅលើទំព័រទិដ្ឋភាពទូទៅហិរញ្ញវត្ថុ។ អ្នកអាចកែប្រែអ្វីដែលត្រូវនាំចេញនៅខាងក្រោម។", + "TITLE": "ទិដ្ឋភាពទូទៅហិរញ្ញវត្ថុ", + "TOTAL_EXPENSES": "ចំណាយសរុប", + "TOTAL_LABOUR": "ពលកម្មសរុប", + "TOTAL_OTHER": "សរុបផ្សេងៗ", + "TOTAL_REVENUE": "ចំណូលសរុប" + }, + "LABOUR": { + "BY": "ដោយ", + "EMPLOYEES": "បុគ្គលិក", + "TABLE": { + "DAILY_TOTAL": "សរុបប្រចាំថ្ងៃ", + "DATE": "កាលបរិច្ឆេទ", + "EMPLOYEE": "បុគ្គលិក", + "LABOUR_COST": "ចំណាយពលកម្ម", + "TASK": "ភារកិច្ច", + "TIME": "ពេល", + "TYPE": "ប្រភេទ" + }, + "TASKS": "ភារកិច្ច", + "TITLE": "ពលកម្ម" + }, + "SUMMARY": { + "SUBTOTAL": "សរុបរង", + "TOTAL": "សរុប", + "TYPE": "ប្រភេទ" + } + }, + "SEARCH": { + "CLEAR_TERMS": "ហេតុអ្វីមិនសាកល្បងស្វែងរកថ្មីមួយផ្សេងទៀត ដើម្បីរកឱកាសថ្មីៗ?", + "CLEAR_TERMS_AND_FILTERS": "ហេតុអ្វីមិនសាកល្បងពាក្យផ្សេងទៀត ឬក៏លុបតម្រងចេញ ដើម្បីរកលទ្ធភាពថ្មី?", + "NO_RESULTS_FOR": "សូមអភ័យទោស យើងមិនអាចរកឃើញលទ្ធផលណាមួយសម្រាប់ពាក្យស្វែងរករបស់អ្នក <1>'{{searchTerm}}' ទេ", + "ZERO": "លទ្ធផល​​ 0" + }, + "SECTION_HEADER": { + "ANIMALS_GROUPS": "ក្រុមសត្វ", + "ANIMALS_INVENTORY": "សារពើភ័ណ្ឌសត្វ", + "ANIMALS_LOCATION": "ទីតាំងសត្វ" + }, + "SELECT": { + "NO_ANIMALS_IN_INVENTORY": "អ្នកមិនមានសត្វនៅក្នុងបញ្ជីស្តុកទេ", + "NO_CROP_VARIETIES": "អ្នកមិនមានពូជដំណាំទេ" + }, + "SENSOR": { + "ARRAY": "សំណុំទិន្នន័យ", + "DAYS_AGO": "{{time}}​ ថ្ងៃកន្លងទៅ", + "DEPTH": "ជម្រៅ", + "DETAIL": { + "ADD_SENSORS": "បន្ថែមឧបករណ៍ចាប់សញ្ញា/សិនស័រ", + "DETECTED_FIELD": "យើងបានរកឃើញទីតាំងវាលស្រែ៖", + "DEVICE_TYPE": "ប្រភេទឧបករណ៍" + }, + "DEVICE_TYPES": { + "DRIP_LINE_PRESSURE_SENSOR": "ឧបករណ៍ចាប់សញ្ញាសម្ពាធបំពង់ស្រោចទឹកតំណក់", + "IR_TEMPERATURE_SENSOR": "ឧបករណ៍ចាប់សីតុណ្ហភាពអ៊ីនហ្វ្រារ៉េដ", + "SOIL_WATER_POTENTIAL_SENSOR": "ឧបករណ៍ចាប់សក្តានុពលទឹកក្នុងដី", + "WEATHER_STATION": "ស្ថានីយអាកាសធាតុ", + "WIND_SPEED_SENSOR": "ឧបករណ៍ចាប់សញ្ញាល្បឿនខ្យល់" + }, + "ESCI": { + "ACTIVE_CONNECTION": "អ្នកមានការតភ្ជាប់ ESci ដែលកំពុងដំណើរការ", + "CONNECT_NEW_SENSOR": "ភ្ជាប់ការដំឡើងសិនស័រថ្មីពី ESci", + "CURRENT_SUPPORT": "បច្ចុប្បន្នយើងគាំទ្រតែសិនស័រពី «ក្រុមហ៊ុនអុិនសេមបលសាយអុិនធីហ្វិច » ប៉ុណ្ណោះ", + "ENSEMBLE_ESID": "ឧបករណ៍ ESID របស់ អុិនសេមបល", + "ENTER_ID": "សូមបញ្ចូលលេខសម្គាល់អង្គភាព​អុិនសេមបលសាយអុិនធីហ្វិច របស់អ្នក", + "MANAGE_LINK": "គ្រប់គ្រងតំណភ្ជាប់ ESci", + "NAME": "ក្រុមហ៊ុន​​អុិនសេមបលសាយអុិនធីហ្វិច", + "ORGANISATION_ID": "លេខសម្គាល់អង្គភាព ESci", + "ORGANISATION_ID_ERROR": "លេខសម្គាល់អង្គភាពមិនត្រឹមត្រូវ", + "ORGANISATION_ID_GENERIC_ERROR": "មិនអាចភ្ជាប់ទៅ ESci បានទេ។ សូមព្យាយាមម្តងទៀតនៅពេលក្រោយ។", + "SEE_ENSEMBLE_SENSOR_LIST": "មើលបញ្ជីឧបករណ៍ចាប់សញ្ញា អុិនសេមបល", + "SHORT_NAME": "ឧបករណ៍ ESci", + "TO_MANAGE_SENSORS": "ដើម្បីគ្រប់គ្រងសិនស័ររបស់អ្នកម្នាក់ៗ សូមភ្ជាប់ទៅកាន់ផ្ទាំងគ្រប់គ្រង ESci នៅ {{url}}" + }, + "HOURS_AGO": "{{time}}​​ ម៉ោងកន្លងទៅ", + "MINUTES_AGO": "{{time}}​​​ នាទីកន្លងទៅ", + "MONTHS_AGO": "{{time}}​​ ខែកន្លងទៅ", + "NO_DATA_FOUND": "មិនមានទិន្នន័យពីឧបករណ៍ចាប់សញ្ញាទេ", + "NO_RECENT_SENSOR_READINGS": "គ្មានទិន្នន័យសិនស័រថ្មីៗ (ក្នុងរយៈពេល 2 ម៉ោងចុងក្រោយ)", + "PARTNER_SENSOR_LIST": "{{partner}} បញ្ជីសិនស័រ", + "READING": { + "BAROMETRIC_PRESSURE": "សម្ពាធបារ៉ូម៉ែត្រ", + "CUMULATIVE_RAINFALL": "បរិមាណទឹកភ្លៀងសរុប", + "LATEST_READING": "ការអានចុងក្រោយ៖", + "RAINFALL_RATE": "អត្រាទឹកភ្លៀង", + "RELATIVE_HUMIDITY": "សំណើមបរិយាកាស", + "SOIL_WATER_CONTENT": "បរិមាណទឹកក្នុងដី", + "SOIL_WATER_POTENTIAL": "សក្តានុពលទឹកក្នុងដី", + "SOLAR_RADIATION": "កាំរស្មីព្រះអាទិត្យ", + "TEMPERATURE": "សីតុណ្ហភាព", + "TYPES": "ប្រភេទទិន្នន័យអាន", + "UNKNOWN": "មិនស្គាល់", + "UPDATE_READINGS": "ធ្វើបច្ចុប្បន្នភាពការអាន", + "WATER_PRESSURE": "សម្ពាធទឹក", + "WIND_DIRECTION": "ទិសខ្យល់", + "WIND_SPEED": "ល្បឿនខ្យល់", + "WIND_SPEED_AND_DIRECTION": "ល្បឿន និងទិសខ្យល់" + }, + "SECONDS_AGO": "{{time}} វិនាទីមុន", + "SENSOR_ARRAY": "សំណុំឧបករណ៍ចាប់សញ្ញា/សំណុំសិនស័រ", + "SENSOR_ARRAYS": "សំណុំឧបករណ៍ចាប់សញ្ញា/សំណុំសិនស័រ", + "STANDALONE_SENSOR": "ឧបករណ៍ចាប់សញ្ញាដាច់ដោយឡែក", + "STANDALONE_SENSORS": "ឧបករណ៍ចាប់សញ្ញាដាច់ដោយឡែក" + }, + "SIGNUP": { + "CHANGES": "អានអំពីការផ្លាស់ប្តូរ", + "EMAIL_INVALID": "អ៊ីមែលមិនត្រឹមត្រូវទេ", + "ENTER_EMAIL": "បញ្ចូលអាសយដ្ឋានអ៊ីមែលរបស់អ្នក", + "EXPIRED_ERROR": "យើងបានធ្វើបច្ចុប្បន្នភាពប្រព័ន្ធហេដ្ឋារចនាសម្ព័ន្ធរបស់យើង ហើយអ្នកនឹងត្រូវកំណត់ពាក្យសម្ងាត់ឡើងវិញ។ សូមពិនិត្យប្រអប់សាររបស់អ្នកដើម្បីបន្ត។", + "EXPIRED_INVITATION_LINK_ERROR": "ការអញ្ជើញមិនត្រឹមត្រូវ ឬបានផុតកំណត់", + "GOOGLE_BUTTON": "បន្តដោយប្រើហ្គូហ្គល", + "INVITED_ERROR": "ការអញ្ជើញចូលរួមកសិដ្ឋានត្រូវបានផ្ញើទៅកាន់អ៊ីមែលរបស់អ្នកហើយ សូមពិនិត្យប្រអប់សារ និងកម្រងសារឥតបានការ របស់អ្នក។", + "LITEFARM_UPDATED": "ឡៃហ្វាម វី​ 3.5 មានរួចហើយ!", + "PASSWORD_ERROR": "ពាក្យសម្ងាត់មិនត្រឹមត្រូវ", + "SIGN_IN": "ចូលគណនី", + "SSO_ERROR": "សូមចូលគណនីដោយចុចប៊ូតុង ហ្គូហ្គល​ខាងលើ", + "USED_INVITATION_LINK_ERROR": "ការអញ្ជើញនេះត្រូវបានប្រើរួចហើយ សូមចូលគណនីដើម្បីចូលប្រើកសិដ្ឋាននេះ", + "WELCOME_BACK": "សូមស្វាគមន៍ត្រឡប់មកវិញ", + "WRONG_BROWSER": "ឡៃហ្វាម មិនត្រូវបានធ្វើឱ្យប្រសើរសម្រាប់កម្មវិធីរុករកនេះទេ។", + "WRONG_BROWSER_BOTTOM": "សូមចូលគណនីដោយប្រើកម្មវិធីក្រូម។" + }, + "SIMPLE_BADGE": { + "PRIVATE": "ឯកជន" + }, + "SLIDE_MENU": { + "CROPS": "ដំណាំ", + "DOCUMENTS": "ឯកសារ", + "FINANCES": "ហិរញ្ញវត្ថុ", + "INSIGHTS": "ការយល់ដឹង", + "MANAGE": "គ្រប់គ្រង", + "TASKS": "ភារកិច្ច" + }, + "STATUS": { + "ACTIVE": "សកម្ម", + "INACTIVE": "អសកម្ម", + "INVITED": "គ្មានសុពលភាព", + "OFFLINE": "ក្រៅបណ្តាញ​ / មិនបានភ្ជាប់បណ្តាញ", + "ONLINE": "ភ្ជាប់បណ្តាញ", + "SENSOR": { + "OFFLINE_TOOLTIP": "ឧបករណ៍មិនបានផ្ញើទិន្នន័យអស់រយៈពេលលើស 12 ម៉ោងហើយ", + "ONLINE_TOOLTIP": "ឧបករណ៍បានផ្ញើទិន្នន័យក្នុងរយៈពេល 12 ម៉ោងចុងក្រោយ" + } + }, + "SURVEY_STACK": { + "PRODUCED": "ផលិតនៅថ្ងៃទី", + "SURVEY_ADDENDUM": "ឧបសម្ព័ន្ធសំណួរស្ទង់មតិ", + "TITLE": "{{certification}} វិញ្ញាបនបត្រពី {{certifier}}" + }, + "SWITCH_OUTRO": { + "BUTTON": "តោះទៅ!", + "DESCRIPTION_BOTTOM": "កំពុងទៅកាន់៖​ ", + "DESCRIPTION_TOP": "ទ្វារសត្វចិញ្ចឹមត្រូវបានបិទជាប់ល្អ។", + "TITLE": "កំពុងប្តូរកសិដ្ឋាន" + }, + "TABLE": { + "LOAD_MORE": "+ ផ្ទុកបន្ថែមទៀត", + "LOADING_TEXT": "កំពុងដំណើរការ...", + "NEXT_TEXT": "បន្ទាប់", + "NO_DATA_TEXT": "រកមិនឃើញជួរទិន្នន័យណាមួយទេ", + "NUMBER_MORE": "+ {{number}}​ ទៀត", + "OF_TEXT": "នៃ", + "PAGE_TEXT": "ទំព័រ", + "PREVIOUS_TEXT": "ពីមុន", + "ROWS_TEXT": "ជួរ" + }, + "TASK": { + "ABANDON": { + "ABANDON": "បោះបង់", + "DATE": "កាលបរិច្ឆេទបោះបង់", + "DATE_ANOTHER": "កាលបរិច្ឆេទមួយទៀត", + "DATE_ORIGINAL": "កាលកំណត់ដើមដំបូង", + "DATE_TODAY": "ថ្ងៃនេះ", + "EXPLANATION": "ការពន្យល់", + "INFO": "ការបោះបង់ភារកិច្ចនេះនឹងប្តូរស្ថានភាពរបស់វាទៅជា “បានបោះបង់” ហើយនឹងដកវាចេញពីបញ្ជី “ត្រូវធ្វើ” និង “មិនទាន់បានផ្តល់ភារកិច្ច” របស់អ្នកប្រើប្រាស់ទាំងអស់។", + "NOTES": "កំណត់ចំណាំអំពីការបោះបង់ភារកិច្ច", + "NOTES_CHAR_LIMIT": "កំណត់ចំណាំត្រូវតែមានតិចជាង 10.000 តួអក្សរ", + "REASON": { + "CROP_FAILURE": "ការបរាជ័យដំណាំ", + "LABOUR_ISSUE": "បញ្ហាការងារ", + "MACHINERY_ISSUE": "បញ្ហាម៉ាសុីន", + "MARKET_PROBLEM": "បញ្ហាទីផ្សារ", + "NO_ANIMALS": "បានបោះបង់ដោយស្វ័យប្រវត្តិ៖ មិនមានសត្វសម្រាប់ភារកិច្ចនេះទេ", + "OTHER": "ផ្សេងទៀត", + "SCHEDULING_ISSUE": "បញ្ហាក្នុងការកំណត់ពេលវេលា", + "WEATHER": "អាកាសធាតុ" + }, + "REASON_FOR_ABANDONMENT": "មូលហេតុនៃការបោះបង់", + "TITLE": "ការបោះបង់ភារកិច្ច", + "WHAT_HAPPENED": "តើមានអ្វីកើតឡើង?", + "WHEN": "ភារកិច្ចត្រូវបានបោះបង់នៅពេលណា?", + "WHICH_DATE": "កាលបរិច្ឆេទណា?" + }, + "ABANDON_TASK": "បោះបង់ភារកិច្ចនេះ", + "ABANDON_TASK_DURATION": "តើមានការងារណាមួយត្រូវបានបញ្ចប់សម្រាប់ភារកិច្ចនេះទេ?", + "ABANDON_TASK_HELPTEXT": "ការងារដែលបានបញ្ចប់លើភារកិច្ចដែលបានបោះបង់នេះ នឹងត្រូវបានបញ្ចូលទៅក្នុងថ្លៃពលកម្ម។ ប្រសិនបើមិនមានការងារណាមួយត្រូវបានបញ្ចប់ទេ សូមជ្រើសរើសជម្រើសនោះជំនួស។", + "ABANDONMENT_DETAILS": "ព័ត៌មានលម្អិតអំពីការបោះបង់ភារកិច្ច", + "ADD_CUSTOM_HARVEST_USE": "បង្កើតការប្រើប្រាស់ផលច្រូតផ្ទាល់ខ្លួន", + "ADD_HARVEST_USE": "បន្ថែមការប្រើប្រាស់ផលច្រូតផ្សេងទៀត", + "ADD_TASK": "បង្កើតភារកិច្ច", + "AMOUNT_TO_ALLOCATE": "បរិមាណដែលត្រូវបែងចែក", + "ANIMAL_MOVEMENT_EXPANDING_SUMMARY_TITLE": "សត្វក្នុងភារកិច្ចនេះ", + "ANIMAL_MOVING_TO_LOCATION": "កំពុងផ្លាស់ទីទៅ៖", + "ANIMALS": "សត្វ", + "ANIMALS_AT_LEAST_ONE_TO_COMPLETE": "ត្រូវជ្រើសរើសយ៉ាងហោចណាស់សត្វមួយដើម្បីបញ្ចប់ភារកិច្ចនេះ។ ដើម្បីដកសត្វទាំងអស់ចេញ សូមបោះបង់ភារកិច្ចជំនួសវិញ។", + "CARD": { + "MULTIPLE_CROPS": "ដំណាំច្រើនប្រភេទ", + "MULTIPLE_LOCATIONS": "ទីតាំងច្រើនកន្លែង", + "NO_LOCATION": "គ្មានទីតាំង" + }, + "COMPLETE": { + "DATE": "ការបរិច្ឆេទបញ្ចប់", + "WHEN": "ភារកិច្ចត្រូវបានបញ្ចប់នៅពេលណា?" + }, + "COMPLETE_HARVEST_QUANTITY": "តើបានប្រមូលផលប៉ុន្មាន?", + "COMPLETE_TASK": "បញ្ចប់ភារកិច្ច", + "COMPLETE_TASK_CHANGES": "តើអ្នកត្រូវធ្វើការកែប្រែអ្វីខ្លះចំពោះភារកិច្ចនេះទេ?", + "COMPLETE_TASK_DURATION": "ភារកិច្ចនេះចំណាយពេលប៉ុន្មានដើម្បីបញ្ចប់?", + "COMPLETION_DETAILS": "ព័ត៌មានលម្អិតអំពីការបញ្ចប់ភារកិច្ច", + "COMPLETION_NOTES": "កំណត់ចំណាំអំពីការបញ្ចប់ភារកិច្ច", + "COMPLETION_NOTES_CHAR_LIMIT": "កំណត់សម្គាល់ត្រូវតែមានប្រវែងតិចជាង 10.000 តួអក្សរ", + "CREATE": { + "FAILED": "មិនអាចបង្កើតភារកិច្ច", + "LOCATION_DELETED": "អ្នកប្រើផ្សេងទៀតបានបញ្ឈប់ទីតាំងដែលអ្នកបានជ្រើសរើស។ សូមផ្ទុកទំព័រឡើងវិញ ដើម្បីទទួលបានស្ថានភាពថ្មីបំផុត។" + }, + "CREATE_CUSTOM_HARVEST_USE": "បង្កើតប្រភេទប្រមូលផលតាមបំណង", + "CURRENT": "ថ្មីៗ", + "DELETE": { + "CANT_DELETE_ABANDON": "ទៅកាន់ផែនការដំណាំ", + "CANT_DELETE_ABANDON_INSTEAD": "តើអ្នកចង់បោះបង់ផែនការដំណាំនេះជំនួសវិញទេ?", + "CANT_DELETE_PLANTING_TASK": "មិនអាចលុបភារកិច្ចដាំដំណាំបានទេ", + "CONFIRM_DELETION": "បញ្ជាក់ការលុប", + "DELETE_TASK": "លុបភារកិច្ច", + "DELETE_TASK_MESSAGE": "ភារកិច្ចនេះនឹងត្រូវលុបចេញពីកសិដ្ឋានរបស់អ្នក។ ប្រសិនបើអ្នកចង់រក្សាទុកកំណត់ត្រាភារកិច្ចនេះ សូមចុច “បោះបង់” ជំនួសវិញ។", + "DELETE_TASK_QUESTION": "លុបភារកិច្ចទេ?", + "FAILED": "ការលុបភារកិច្ចបានបរាជ័យ", + "SUCCESS": "ការលុបភារកិច្ចបានជោគជ័យ" + }, + "DESCRIBE_HARVEST_USE": "ពិពណ៌នាអំពីការប្រើប្រាស់ផលច្រូត", + "DETAILS": "ព័ត៌មានលំអិត", + "DID_YOU_ENJOY": "តើអ្នកចូលចិត្តភារកិច្ចនេះទេ?", + "DID_YOU_GET_RESULTS": "តើអ្នកបានទទួលលទ្ធផលពីមន្ទីរពិសោធន៍ហើយឬនៅ?", + "DUE_DATE": "ថ្ងៃកំណត់", + "DURATION": "រយះពេល", + "FILTER": { + "ASCENDING": "ចាស់បំផុតមុន", + "ASSIGNEE": "អ្នកទទួលភារកិច្ច", + "CROP": "ដំណាំ", + "DATE_RANGE": "តម្រងតាមចន្លោះកាលបរិច្ឆេទ", + "DESCENDING": "ថ្មីបំផុតមុន", + "LOCATION": "ទីតាំង", + "MY_TASK": "ភារកិច្ចរបស់ខ្ញុំ", + "SORT_BY": "តម្រៀបតាម", + "STATUS": "ស្ថានភាព", + "TITLE": "តម្រងភារកិច្ច", + "TYPE": "ប្រភេទ", + "UNASSIGNED": "មិនទាន់បានផ្តល់ភារកិច្ច", + "VIEW": "មើល" + }, + "HARVEST_USE": "ការប្រើប្រាស់ទិន្នផលប្រមូលផល", + "HARVEST_USE_ALREADY_EXISTS": "ការប្រើប្រាស់ទិន្នផលប្រមូលផលនេះមានរួចហើយ", + "HOW_WILL_HARVEST_BE_USED": "តើទិន្នផលប្រមូលផលនេះនឹងត្រូវប្រើប្រាស់យ៉ាងដូចម្តេច?", + "IRRIGATION_LOCATION": "សូមជ្រើសរើសទីតាំងប្រព័ន្ធស្រោចស្រព", + "LAB_DOCUMENTS": "ឯកសារមន្ទីរពិសោធន៍", + "LOCATIONS": "ទីតាំង", + "NO_LOCATIONS_FOR_TASK": "ភារកិច្ចនេះមិនត្រូវការទីតាំងជាក់លាក់ទេ", + "NO_TASKS_TO_DISPLAY": "មិនមានភារកិច្ចណាមួយសម្រាប់បង្ហាញទេ។", + "NO_WORK_DONE": "មិនមានការងារណាមួយត្រូវបានបញ្ចប់ទេ", + "PAGE_TITLE": "ភារកិច្ច", + "PREFER_NOT_TO_SAY": "ខ្ញុំសូមមិនបញ្ជាក់", + "PROVIDE_RATING": "សូមផ្តល់ការវាយតម្លៃ", + "QUANTITY_CANNOT_EXCEED": "បរិមាណទិន្នផលដែលបានប្រើ មិនអាចលើសពីបរិមាណដែលបានកំណត់សម្រាប់ការបែងចែកបានទេ", + "RATE_THIS_TASK": "សូមវាយតម្លៃភារកិច្ចនេះ", + "REMOVE_HARVEST_USE": "លុប", + "SELECT_ANIMALS": "ជ្រើសរើសសត្វ", + "SELECT_DATE": "សូមជ្រើសរើសកាលបរិច្ឆេទភារកិច្ច", + "SELECT_TASK_LOCATIONS": "សូមជ្រើសរើសទីតាំងភារកិច្ច", + "SELECT_WILD_CROP": "ភារកិច្ចនេះផ្តោតលើដំណាំព្រៃ", + "SOIL_AMENDMENT_LOCATION": "សូមជ្រើសរើសទីតាំងកែលម្អដី", + "SOIL_SAMPLING_LOCATION": "ជ្រើសរើសទីតាំងយកសំណាកដី(មួយរឺច្រើនកន្លែង)", + "STATUS": { + "ABANDONED": "បោះចោល", + "COMPLETED": "បញ្ចប់", + "FOR_REVIEW": "ដើម្បីពិនិត្យ", + "LATE": "យឺត", + "PLANNED": "មានផែនការ" + }, + "TASK": "ភារកិច្ច", + "TASKS_COUNT_one": "{{count}} ភារកិច្ច", + "TASKS_COUNT_other": "{{count}} ភារកិច្ច", + "TRANSPLANT": "ស្ទូង", + "TRANSPLANT_LOCATIONS": "ជ្រើសរើសទីតាំងស្ទូង", + "UNASSIGNED": "មិនទាន់បានផ្តល់ភារកិច្ច", + "UPLOAD_LAB_DOCUMENT": "បញ្ចូលឯកសារមន្ទីរពិសោធន៍", + "WILL_SAVE_ONLINE": "នឹងរក្សាទុកនៅពេលភ្ជាប់អ៊ីនធឺណិត" + }, + "TIME_STRIP": { + "NEXT_TIME_SLOT": "ចន្លោះពេលបន្ទាប់", + "PREVIOUS_TIME_SLOT": "ចន្លោះពេលមុន" + }, + "UNIT": { + "TIME": { + "DAY": "ថ្ងៃ", + "MONTH": "ខែ", + "WEEK": "សប្តាហ៍", + "YEAR": "ឆ្នាំ" + }, + "VALID_VALUE": "សូមបញ្ចូលតម្លៃចន្លោះពី 0–" + }, + "UNKNOWN_RECORD": { + "CANT_FIND": "អុប! យើងមិនអាចរកឃើញវាបានទេ។", + "MAYBE_LATER": "ប្រហែលជាវានឹង បង្ហាញនៅពេលក្រោយ។", + "UNKNOWN_RECORD": "កំណត់ត្រាមិនស្គាល់" + }, + "UPLOADER": { + "CHANGE_IMAGE": "ផ្លាស់ប្តូររូបភាព", + "CLICK_TO_UPLOAD": "ចុចដើម្បីបញ្ចូលឯកសារ", + "DRAG_DROP": "ឬអូសហើយទម្លាក់", + "REMOVE_IMAGE": "លុបរូបភាព", + "UNSUPPORTED_FILE_TYPE": "សូមបញ្ចូលរូបភាព PNG, JPG, GIF ឬ WebP", + "UPLOAD_IMAGE": "បញ្ចូលរូបភាព" + }, + "WAGE": { + "ERROR": "ប្រាក់ឈ្នួលត្រូវតែជាលេខទសភាគត្រឹមត្រូវ និងមិនមែនជាតម្លៃអវិជ្ជមានឡើយ", + "HOURLY_WAGE": "ប្រាក់ឈ្នួលជាម៉ោង", + "HOURLY_WAGE_RANGE_ERROR": "ប្រាក់ឈ្នួលតាមម៉ោងត្រូវតែជាលេខវិជ្ជមាន និងតិចជាង 999.999.999", + "HOURLY_WAGE_TOOLTIP": "ប្រាក់ឈ្នួលសម្រាប់ភារកិច្ចនេះនឹងជំនួសប្រាក់ឈ្នួលលំនាំដើមរបស់អ្នកទទួលភារកិច្ច។ ប្រាក់ឈ្នួលលំនាំដើមរបស់កម្មករអាចគ្រប់គ្រងបាននៅផ្ទាំង ប្រជាជន។" + }, + "WEATHER": { + "FROST_EXPECTED": "⚠️រំពឹងថាមានកកទឹក (ទាប {{threshold}})", + "FROST_RISK": "ហានិភ័យកកទឹក", + "HUMIDITY": "សំណើម", + "PRECIPITATION": "ទឹកភ្លៀង", + "TITLE": "អាកាសធាតុ និងលក្ខខណ្ឌ", + "WIND": "ខ្យល់បក់" + }, + "WELCOME_SCREEN": { + "BUTTON": "ចាប់ផ្តើមបានហើយ" + }, + "YEAR_SELECTOR": { + "TITLE": "ជ្រើសរើសឆ្នាំ" + } +} diff --git a/packages/webapp/src/apiConfig.js b/packages/webapp/src/apiConfig.js index ed0dbe4aec..f22ad66448 100644 --- a/packages/webapp/src/apiConfig.js +++ b/packages/webapp/src/apiConfig.js @@ -102,7 +102,7 @@ export const marketDirectoryPartnersUrl = `${URI}/market_directory_partners`; export const supportTicketUrl = `${URI}/support_ticket`; export const logUserInfoUrl = `${URI}/userLog`; export const offlineEventLogUrl = `${URI}/offline_event_log`; -export const tapeSurveyUrl = `${URI}/tape_survey`; +export const surveyResponseUrl = `${URI}/survey_response`; export const farmNoteUrl = `${URI}/farm_notes`; export const farmNotesReadUrl = `${URI}/farm_notes_read`; diff --git a/packages/webapp/src/containers/Consent/locales/km/Owner.Consent.md b/packages/webapp/src/containers/Consent/locales/km/Owner.Consent.md new file mode 100644 index 0000000000..53647c1732 --- /dev/null +++ b/packages/webapp/src/containers/Consent/locales/km/Owner.Consent.md @@ -0,0 +1,177 @@ +##### កំណែទី 7៖ ថ្ងៃទី 12 ខែធ្នូ ឆ្នាំ 2024 + +#### ទម្រង់ការយល់ព្រមដោយបានដឹងព័ត៌មាន និងគោលនយោបាយឯកជនភាព (ម្ចាស់កសិដ្ឋាន និងអ្នកគ្រប់គ្រងកសិដ្ឋាន) + +ស្វាគមន៍មកកាន់ឡៃហ្វាម! + +យើងយល់ថា ឯកជនភាពរបស់អ្នក និងការការពារទិន្នន័យរបស់អ្នកគឺមានសារៈសំខាន់សម្រាប់អ្នក។ យើងបានបង្កើតទម្រង់ការយល់ព្រមដោយមានព័ត៌មានគ្រប់គ្រាន់ និងគោលការណ៍ឯកជនភាពនេះ ដើម្បីឱ្យអ្នកយល់ថា យើងប្រមូល ប្រើប្រាស់ និងចែករំលែកព័ត៌មានរបស់អ្នកយ៉ាងដូចម្តេច និងនៅពេលណា ហើយដើម្បីធានាថា យើងទទួលបានការយល់ព្រមពីអ្នកមុនពេលធ្វើដូច្នេះ។ សូមចងចាំថា អ្នកនឹងត្រូវផ្តល់ការយល់ព្រមចំពោះការប្រមូល និងការប្រើប្រាស់ទិន្នន័យរបស់អ្នក ដូចដែលបានពិពណ៌នានៅក្នុងទម្រង់ការយល់ព្រមដោយមានព័ត៌មានគ្រប់គ្រាន់ និងគោលការណ៍ឯកជនភាពនេះ **សម្រាប់កសិដ្ឋាននីមួយៗដែលត្រូវបានភ្ជាប់ ឬដែលអ្នកមានទំនាក់ទំនងជាមួយ តាមរយៈគណនីរបស់អ្នកនៅលើវេទិកា ឡៃហ្វាម**។ ប្រសិនបើអ្នកមិនយល់ព្រមនឹងការអនុវត្តរបស់យើង ដូចដែលបានគូសបញ្ជាក់នៅក្នុងទម្រង់ការយល់ព្រមដោយមានព័ត៌មានគ្រប់គ្រាន់ និងគោលការណ៍ឯកជនភាពនេះទេ អ្នកនឹងមិនអាចប្រើប្រាស់ប្រព័ន្ធ ឡៃហ្វាម បានឡើយ។ + +#### តើអ្វីទៅជា ឡៃហ្វាម? + +ឡៃហ្វាម គឹជាគម្រោងស្រាវជ្រាវវិទ្យាសាស្ត្របែបចូលរួមមួយ ដែលរៀបចំឡើងនៅសាកលវិទ្យាល័យ ប្រីទិស កូឡុំបៀ ដើម្បីជួយកែលម្អការទទួលបានបច្ចេកវិទ្យាកសិកម្មឌីជីថលសម្រាប់សហគមន៍កសិកម្ម និងអភិវឌ្ឍការយល់ដឹងឱ្យកាន់តែប្រសើរឡើងអំពីផ្លូវឆ្ពោះទៅរកកសិកម្មប្រកបដោយនិរន្តរភាព។ សាកលវិទ្យាល័យ ប្រីទិស កូឡុំបៀ ធ្វើការជាមួយអង្គការកសិករដើម្បីសាកល្បង និងវាយតម្លៃឧបករណ៍ ក៏ដូចជាចំណេះដឹងនានា ដើម្បីជួយកសិករគ្រប់គ្រងកសិដ្ឋានរបស់ពួកគេតាមរបៀបដែលទទួលបានផលចំណេញកាន់តែច្រើន និងមាននិរន្តរភាពផ្នែកបរិស្ថាន និងសង្គម។ កូដមូលដ្ឋានរបស់ ឡៃហ្វាម គឺមិនគិតថ្លៃ និងជាប្រភពបើកចំហ (GPLv3) ដើម្បីឱ្យអ្នកស្រាវជ្រាវ អ្នកជំនាញ និងអ្នកអភិវឌ្ឍន៍ទូទាំងពិភពលោកអាចជួយកែលម្អសេវាកម្មនានាដែលផ្តល់ជូនសហគមន៍កសិកម្ម។ ឡៃហ្វាម គឺជាអង្គភាពមិនរកប្រាក់ចំណេញ។ + +#### នរណាខ្លះជាក្រុមការងារឡៃហ្វាម? + +ក្រុមការងារ ឡៃហ្វាម គឺជាក្រុមពហុជំនាញដែលរួមមានអ្នកវិទ្យាសាស្ត្រ អ្នកស្រាវជ្រាវ កសិករ អ្នករចនា និងអ្នកជំនាញផ្នែកកម្មវិធីកុំព្យូទ័រ។ ដំបូងឡើយ ក្រុមការងារនេះត្រូវបានបង្កើតឡើងនៅសាកលវិទ្យាល័យ ប្រីទិស កូឡុំបៀ (UBC) ហើយបានពង្រីកខ្លួនរហូតរួមបញ្ចូលទាំងបណ្តាញសកលបែបចូលរួមនៃបុគ្គល និងអង្គការនានា។ អ្នកស្រាវជ្រាវចម្បងគឺ បណ្ឌិត ហ្សៀ មេហរ៉ាប៊ី (សាកលវិទ្យាល័យ កូឡូរ៉ាដូ) និង បណ្ឌិត ហាណាក់ វីតមិន (hannah.wittman@ubc.ca) ព្រមទាំង បណ្ឌិត ស៊ន ស្មុកល័រ នាយកមជ្ឈមណ្ឌលសម្រាប់ប្រព័ន្ធស្បៀងអាហារប្រកបដោយនិរន្តរភាព នៅកសិដ្ឋាននៃសាកលវិទ្យាល័យ ប្រីទិស កូឡុំបៀ។ + +#### តើអ្នកណាជាអ្នកផ្តល់មូលនិធិដល់ ឡៃហ្វាម? + +ឡៃហ្វាម ត្រូវបានផ្តល់មូលនិធិដោយមជ្ឈមណ្ឌលសម្រាប់ប្រព័ន្ធស្បៀងអាហារប្រកបដោយនិរន្តរភាពនៅ សាកលវិទ្យាល័យ ប្រីទិស កូឡុំបៀ និងជំនួយឥតសំណងផ្សេងៗទៀត។ សម្រាប់បញ្ជីឈ្មោះពេញលេញ សូមចូលទៅកាន់៖ https://ubcfarm.ubc.ca/csfs-research/litefarm/។ អ្នកផ្តល់មូលនិធិពីខាងក្រៅរបស់យើងមិនមានសិទ្ធិសម្រេចក្នុងការដំណើរការ និងការគ្រប់គ្រង ឡៃហ្វាម ឡើយ ហើយពួកគេមិនអាចចូលប្រើប្រាស់ព័ត៌មានផ្ទាល់ខ្លួនណាមួយដែលរក្សាទុកនៅលើប្រព័ន្ធនេះបានទេ។ បច្ចុប្បន្ននេះ ទម្រង់ផ្តល់មូលនិធិរបស់យើងគឺពឹងផ្អែកលើអ្នកបរិច្ចាគ និងជំនួយឥតសំណង។ + +#### ហេតុអ្វីបានជាយើងធ្វើគម្រោងនេះ? + +យើងកត់សម្គាល់ឃើញនូវកង្វះខាតក្នុងការទទួលបានសេវាបច្ចេកវិទ្យាឌីជីថលរបស់កសិករ អត្រានៃការយកទៅប្រើប្រាស់នៅមានកម្រិតទាប និងតម្រូវការដែលបានលើកឡើងដោយកសិករក្នុងការបញ្ចូលគ្នានូវសេវាក្របគ្រងទិន្នន័យកសិកម្មជាច្រើន ទៅក្នុងប្រព័ន្ធតែមួយដែលមិនមែនដើម្បីគោលបំណងពាណិជ្ជកម្ម។ យើងចង់បង្កើតដំណោះស្រាយមួយដែលជួយកសិករក្នុងការដំណើរការអាជីវកម្មរបស់ពួកគេតាមរបៀបដែលមាននិរន្តរភាពជាងមុន ទាំងផ្នែកហិរញ្ញវត្ថុ និងប្រព័ន្ធអេកូឡូស៊ី ព្រមទាំងជួយជំរុញវិទ្យាសាស្ត្រនៃនិរន្តរភាពឱ្យកាន់តែរីកចម្រើនផងដែរ។ + +#### តើទិន្នន័យអ្វីខ្លះដែលយើងប្រមូល? + +ផ្អែកលើផ្នែកនៃប្រព័ន្ធ ឡៃហ្វាម ដែលអ្នកប្រើប្រាស់ យើងអាចនឹងប្រមូលព័ត៌មានប្រភេទផ្សេងៗគ្នា៖ + +**ព័ត៌មានផ្ទាល់ខ្លួន** + +"ព័ត៌មានផ្ទាល់ខ្លួន" សំដៅលើព័ត៌មានណាមួយដែលអាចប្រើដើម្បីកំណត់អត្តសញ្ញាណរបស់អ្នក ឬកម្មកររបស់អ្នក។ ឡៃហ្វាម នឹងមិនបង្ហាញព័ត៌មានផ្ទាល់ខ្លួនទៅកាន់ភាគីទីបីឡើយ ប្រសិនបើគ្មានការយល់ព្រមច្បាស់លាស់ពីអ្នក។ ព័ត៌មានទាំងនេះរួមមាន៖ + +- ព័ត៌មានទំនាក់ទំនង (ឈ្មោះ, អាសយដ្ឋាន, លេខទូរសព្ទ, អាសយដ្ឋានអ៊ីមែល) + +- ព័ត៌មានប្រជាសាស្ត្រ (ភេទ, ឆ្នាំកំណើត, ភាសាដែលពេញចិត្ត, ប្រទេស, រូបិយប័ណ្ណ) + +- ព័ត៌មានអាជីវកម្ម (ឈ្មោះកសិដ្ឋាន, អាសយដ្ឋានកសិដ្ឋាន, កូអរដោនេកសិដ្ឋាន) + +- រូបថត + +- អាសយដ្ឋានពិធីការអ៊ីនធឺណិត (IP) + +- ព័ត៌មានកម្មករ (ឈ្មោះ, តួនាទីក្នុងកសិដ្ឋាន, អាសយដ្ឋានអ៊ីមែល) + +- ទីតាំងភូមិសាស្ត្រ (ឧទាហរណ៍៖ កូអរដោនេ ជីភីអែស នៃទីតាំងកសិដ្ឋាន ព្រំប្រទល់ទីតាំង ។ល។) + +**ព័ត៌មានគ្រប់គ្រងកសិដ្ឋាន** + +ឡៃហ្វាម ប្រើប្រាស់ព័ត៌មានគ្រប់គ្រងដែលអ្នកបានបញ្ចូលទៅក្នុងកម្មវិធី ដើម្បីបង្កើតជាការយល់ដឹងស៊ីជម្រៅអំពីអត្ថប្រយោជន៍ ឬផលប៉ះពាល់ផ្នែកហិរញ្ញវត្ថុ បរិស្ថាន និងសង្គម នៃការសម្រេចចិត្តគ្រប់គ្រងរបស់អ្នក។ យើងធ្វើឱ្យទិន្នន័យនេះទៅជាអនាមិកដើម្បីធ្វើការស្រាវជ្រាវការអប់រំបែបមិនរកប្រាក់ចំណេញ អំពីប្រព័ន្ធស្បៀងអាហារប្រកបដោយនិរន្តរភាព។ ដោយសារតែទិន្នន័យនេះត្រូវបានធ្វើឱ្យទៅជាអនាមិកនៅពេលប្រើប្រាស់ក្នុងការស្រាវជ្រាវរបស់យើង វាមិនអាចស្វែងរកដានត្រឡប់មកកាន់អ្នក ឬកសិដ្ឋានរបស់អ្នកបានឡើយ។ ទិន្នន័យនេះរួមមាន៖ + +- ព័ត៌មានទីតាំងកសិដ្ឋាន៖ ប្រភេទទីតាំងផ្សេងៗគ្នានៅក្នុងកសិដ្ឋាន រួមមានទំហំ, ឈ្មោះ, ដំណាំដែលបានដាំដុះតាមទីតាំង, ស្ថានភាពសរីរាង្គ, និងលក្ខណៈសម្បត្តិផ្សេងទៀតជាក់លាក់ទៅតាមប្រភេទទីតាំង + +- ព័ត៌មានដំណាំ៖ ប្រភេទដំណាំ, ពូជ, អ្នកផ្គត់ផ្គង់, ឈ្មោះទូទៅ, ប្រភេទជីវសាស្ត្រ, ពួកជីវសាស្ត្រ, ក្រុមដំណាំ, ស្ថានភាពវិញ្ញាបនបត្រសរីរាង្គ និងព័ត៌មានគាំទ្រផ្សេងៗ + +- ព័ត៌មានគ្រប់គ្រងដំណាំ៖ រួមមានកាលបរិច្ឆេទចាប់ផ្តើម និងបញ្ចប់, វិធីសាស្ត្រដាំ, វិធីសាស្ត្រស្ទូង, អាយុកាលរបស់ដំណាំ, ភារកិច្ចដែលពាក់ព័ន្ធនឹងផែនការ, តម្លៃប៉ាន់ស្មាននៃដំណាំ, ទិន្នផលប៉ាន់ស្មាននៃដំណាំ និងព័ត៌មានផ្សេងៗទៀត។ + +- ព័ត៌មានអំពីភារកិច្ចដែលបានអនុវត្តនៅក្នុងកសិដ្ឋាន៖ អ្នកទទួលខុសត្រូវ, អ្នកបង្កើត, រយៈពេល, ទីតាំង, ដំណាំដែលរងផលប៉ះពាល់, ធាតុចូល, កំណត់សម្គាល់, កាលបរិច្ឆេទ, ស្ថានភាពនៃការបញ្ចប់កិច្ចការ ។ល។ + +- ព័ត៌មានគ្រប់គ្រងសត្វល្អិតចង្រៃ៖ ឈ្មោះផលិតផល, បរិមាណផលិតផលដែលបានប្រើ, គោលដៅនៃការប្រើប្រាស់ (ពោលគឺ ឈ្មោះសត្វល្អិតចង្រៃ ឬជំងឺ), ឈ្មោះទូទៅ, ឈ្មោះវិទ្យាសាស្ត្រ, ក្រុម, ឈ្មោះសារធាតុសកម្ម, កំហាប់សារធាតុសកម្ម, រយៈពេលអត់បាញ់ថ្នាំមុនប្រមូលផល, រយៈពេលផ្អាកចូលចម្ការក្រោយបាញ់ថ្នាំ, ប្រភេទនៃការគ្រប់គ្រង, ទីតាំង និងដំណាំគោលដៅ។ + +- ព័ត៌មានប្រមូលផល៖ វាលស្រែ/ចម្ការដែលបានប្រមូលផល, ដំណាំដែលបានប្រមូលផល, បរិមាណប្រមូលផលបាន, ការប្រើប្រាស់ផលដែលប្រមូលបាន។ + +- ព័ត៌មានបណ្តុះគ្រាប់ពូជ៖ ទីតាំងដែលបានបណ្តុះ, ដំណាំដែលបានបណ្តុះ, ជម្រៅចន្លោះជួរ, ប្រវែង, ទទឹង និងអត្រាដាំដុះ។ + +- ព័ត៌មានការងារក្នុងចម្ការ៖ ទីតាំង, ដំណាំ, ប្រភេទនៃការងារ, កំណត់សម្គាល់។ + +- ព័ត៌មានដី៖ ទីតាំង ជម្រៅ វាយនភាពដី ភាគរយនៃប៉ូតាស្យូម ផូស្វ័រ អាសូត សារធាតុសរីរាង្គ កាបូនសរីរាង្គ កាបូនអសរីរាង្គ កាបូនសរុប ស៊ុលហ្វួរ កាល់ស្យូម ម៉ាញេស្យូម សូដ្យូម ស័ង្កសី ម៉ង់ហ្គាណែស ដែក ទង់ដែង បូរ៉ុង សមត្ថភាពប្តូរកាចុង (CEC) កម្រិតអាស៊ីត-បាស ដង់ស៊ីតេដីសរុប។ + +- ទិន្នន័យឧបករណ៍ចាប់សញ្ញា ដូចជាកម្រិតជាតិទឹកក្នុងដី និងសីតុណ្ហភាពដី ដែលអ្នកជាកសិករ បញ្ជូនទៅកាន់កម្មវិធីតាមរយៈការភ្ជាប់ ឡៃហ្វាម ជាមួយឧបករណ៍ចាប់សញ្ញារបស់ភាគីទីបី។ + +- ព័ត៌មានប្រព័ន្ធស្រោចស្រព៖ ទីតាំង, ដំណាំ, ប្រភេទនៃការស្រោចស្រព, អត្រាលំហូរទឹក, រយៈពេលហូរទឹកសរុប។ + +- ព័ត៌មានពិនិត្យតាមដានចម្ការ៖ ទីតាំង, ដំណាំ, ប្រភេទ, សកម្មភាពដែលត្រូវធ្វើ (បាទ/ចាស ឬ ទេ)។ + +- ព័ត៌មានផ្សេងៗទៀត៖ ទីតាំង, ដំណាំ, កំណត់សម្គាល់។ + +- ព័ត៌មានពាក់ព័ន្ធនឹងការបញ្ចប់ភារកិច្ច រួមមាន៖ កាលបរិច្ឆេទ, រយៈពេលធ្វើការ, អារម្មណ៍ (សប្បាយចិត្ត, សប្បាយចិត្តខ្លាំង, កើតទុក្ខ, កើតទុក្ខខ្លាំង, ធម្មតា), កំណត់សម្គាល់លើការងារ។ + +- ព័ត៌មានចំណាយ៖ កាលបរិច្ឆេទ, ប្រភេទ, ឈ្មោះ, ចំនួនទឹកប្រាក់ចំណាយ។ + +- ព័ត៌មានលក់ដូរ៖ កាលបរិច្ឆេទ, ឈ្មោះអ្នកទិញ/ទីផ្សារ, ដំណាំ, បរិមាណលក់ដាច់ (គីឡូក្រាម), ប្រាក់ចំណូល។ + +- ព័ត៌មានលម្អិតរបស់កម្មករ៖ ចំនួនកម្មករដែលបានចុះឈ្មោះ, ប្រាក់ឈ្នួលម៉ោង, អាសយដ្ឋានអ៊ីមែល, តួនាទី, ឈ្មោះ ។ល។ + +- ព័ត៌មានលម្អិតជាក់លាក់របស់កសិដ្ឋាន៖ ប្រព័ន្ធរង្វាស់រង្វាល់ដែលពេញចិត្ត (ឧទាហរណ៍៖ ប្រព័ន្ធម៉ែត្រ ឬប្រព័ន្ធអង់គ្លេស), រូបិយប័ណ្ណ, ថាតើកសិដ្ឋានកំពុងស្នើសុំវិញ្ញាបនបត្រដែរឬទេ, អង្គភាពផ្តល់វិញ្ញាបនបត្រ, លក្ខណៈរងដាំដុះ, លក្ខណៈជួរដាំដុះ។ + +- ព័ត៌មានសត្វ៖ ឈ្មោះសត្វដាច់ដោយឡែក ឬជាហ្វូង, ប្រភេទ, ពូជ, ភេទ, កាលបរិច្ឆេទនាំចូល ឬថ្ងៃបង្កើត និងព័ត៌មានលម្អិតអំពីការកំណត់អត្តសញ្ញាណផ្សេងទៀត + +- ព័ត៌មានបម្លាស់ទីសត្វ៖ ទីតាំង, មូលហេតុនៃការបម្លាស់ទី និងកាលបរិច្ឆេទនៃការបម្លាស់ទី + +**ទិន្នន័យនៃការប្រើប្រាស់** + +យើងប្រមូលទិន្នន័យនៃការប្រើប្រាស់ (ពោលគឺ ស្ថិតិទូទៅអំពីអ្នកប្រើប្រាស់, ទម្រង់ចរាចរណ៍អ៊ីនធឺណិត និងរបៀបដែលអ្នកប្រើប្រាស់ឆ្លើយតបទៅនឹងមុខងារផ្សេងៗនៃគេហទំព័រ) ដើម្បីកែលម្អគុណភាពនៃសេវាកម្មដែលយើងផ្តល់ជូនអ្នក។ ទិន្នន័យប្រភេទនេះរួមមាន៖ ពេលវេលាដែលអ្នកចូលប្រើ ឡៃហ្វាម, ទំព័រដែលអ្នកស្នើសុំមើល, រយៈពេលដែលអ្នកចូលមើលគេហទំព័រ, របៀបដែលអ្នកបញ្ជាប្រើប្រាស់កម្មវិធី និងព័ត៌មានលម្អិតបច្ចេកទេសអំពីឧបករណ៍របស់អ្នក (ឧទាហរណ៍៖ កម្មវិធីរុករកគេហទំព័រ, ប្រភេទអេក្រង់ និងអង្គដំណើរការ)។ ទិន្នន័យនេះនឹងត្រូវបានភ្ជាប់ទៅនឹងឈ្មោះអ្នកប្រើប្រាស់ ឡៃហ្វាម របស់អ្នក (ប្រសិនបើអ្នកបានចូលប្រើប្រាស់កម្មវិធី) ឬភ្ជាប់ទៅនឹងអាសយដ្ឋាន IP របស់អ្នក (ប្រសិនបើអ្នកមិនបានចូលប្រើប្រាស់កម្មវិធី)។ យើងអាចនឹងប្រើប្រាស់កម្មវិធីដូចជា Google Analytics ដើម្បីប្រមូល និងវិភាគ ទិន្នន័យប្រើប្រាស់ ប៉ុន្តែនៅក្នុងករណីទាំងនេះ ព័ត៌មានផ្ទាល់ខ្លួនទាំងអស់នឹងត្រូវ លាក់អត្តសញ្ញាណ។ + +**តើយើងប្រើប្រាស់ទិន្នន័យដោយរបៀបណា?** + +មានវិធីសាស្ត្រចម្បងចំនួនបីដែលយើងប្រើប្រាស់ទិន្នន័យរបស់អ្នក៖ + +- ដើម្បីកែលម្អសេវាកម្មបង្ហាញទិន្នន័យកសិកម្មជារូបភាពដែលយើងផ្តល់ជូនអ្នក៖ ដូចដែលបានពិពណ៌នាខាងលើ យើងប្រើប្រាស់ទិន្នន័យប្រើប្រាស់របស់អ្នក (ពោលគឺ ព័ត៌មានទូទៅអំពីរបៀបដែលអ្នកប្រកបទំនាក់ទំនងជាមួយប្រព័ន្ធ ឡៃហ្វាម) ដើម្បីកែលម្អប្រព័ន្ធ ឡៃហ្វាម និងសេវាកម្មដែលវាផ្តល់ជូន។ + +- ដើម្បីបង្កើតការយល់ដឹងអំពីអត្ថប្រយោជន៍ ឬផលប៉ះពាល់ផ្នែកហិរញ្ញវត្ថុ បរិស្ថាន និងសង្គមនៃការសម្រេចចិត្តក្នុងការគ្រប់គ្រងរបស់អ្នក៖ វេទិកា ឡៃហ្វាម ប្រើប្រាស់ទិន្នន័យការគ្រប់គ្រងដែលអ្នកបានបញ្ចូលទៅក្នុងកម្មវិធី (សូមមើលផ្នែក “ព័ត៌មានគ្រប់គ្រងកសិដ្ឋាន” ខាងលើសម្រាប់បញ្ជីពេញលេញ) រួមជាមួយអាល់ហ្គរីធម៍ដែលមានស្រាប់ និងទិន្នន័យសាធារណៈមួយចំនួន (ឧទាហរណ៍ ព័ត៌មានពីស្ថានីយ៍អាកាសធាតុក្នុងតំបន់ កូអ៊ីហ្វីស្យង់ដំណាំ សមាសធាតុសារធាតុចិញ្ចឹមរបស់ដំណាំ និងជី ទិន្នន័យការរស់នៅនៃប្រភេទសត្វ និងទិន្នន័យភូមិសាស្ត្រខ្ពស់ទាប) ដើម្បីបង្កើតការយល់ដឹងអំពីអត្ថប្រយោជន៍ ឬផលប៉ះពាល់ផ្នែកហិរញ្ញវត្ថុ បរិស្ថាន និងសង្គមនៃការសម្រេចចិត្តក្នុងការគ្រប់គ្រងរបស់អ្នក។ + +- ដើម្បីធ្វើការស្រាវជ្រាវការអប់រំបែបមិនរកប្រាក់ចំណេញ អំពីប្រព័ន្ធស្បៀងអាហារប្រកបដោយនិរន្តរភាព៖ រួមជាមួយដៃគូសហការផ្នែកការអប់រំរបស់យើង យើងនឹងប្រើប្រាស់ទិន្នន័យគ្រប់គ្រងកសិដ្ឋានបែបអនាមិករបស់អ្នក (សូមមើលផ្នែក "ព័ត៌មានគ្រប់គ្រងកសិដ្ឋាន" ខាងលើសម្រាប់បញ្ជីពេញលេញ) ដើម្បីធ្វើការស្រាវជ្រាវផ្នែកកសិសាស្ត្រ អេកូឡូស៊ី និងការស្រាវជ្រាវការអប់រំផ្អែកលើប្រព័ន្ធស្បៀងអាហារ។ ការស្រាវជ្រាវមួយចំនួននេះ នឹងត្រូវធ្វើឡើងដោយនិស្សិត ដែលជាផ្នែកមួយនៃថ្នាក់បរិញ្ញាបត្រ និងថ្នាក់ក្រោយបរិញ្ញាបត្ររបស់ពួកគេ។ + +យើងនឹងវាយតម្លៃរាល់សំណើគម្រោងនីមួយៗយ៉ាងម៉ត់ចត់ ដើម្បីធានាថាទិន្នន័យរបស់អ្នកត្រូវបានប្រើប្រាស់ប្រកបដោយប្រសិទ្ធភាពក្នុងការលើកកម្ពស់ចំណេះដឹងអំពីប្រព័ន្ធស្បៀងអាហារប្រកបដោយនិរន្តរភាព ជួយកសិករក្នុងការសម្រេចចិត្តគ្រប់គ្រងប្រកបដោយនិរន្តរភាព និងជះឥទ្ធិពលលើគោលនយោបាយសាធារណៈដើម្បីជាប្រយោជន៍ដល់កសិករ។ យើងនឹងផ្តល់ដំណឹងជូនអ្នកជាបន្តបន្ទាប់អំពីគម្រោងស្រាវជ្រាវនានាតាមរយៈអ៊ីមែល (លុះត្រាតែអ្នកចង់បដិសេធមិនទទួល) ហើយអ្នកតែងតែអាចទាក់ទងមកយើងដើម្បីស្វែងយល់បន្ថែមអំពីការស្រាវជ្រាវដែលទិន្នន័យរបស់អ្នកកំពុងជួយជ្រោមជ្រែងឱ្យលេចចេញជារូបរាង។ + +**តើយើងចែករំលែកអ្វីខ្លះ?** + +យើងនឹងចែករំលែកទិន្នន័យរបស់អ្នកជាមួយភាគីទីបី លុះត្រាតែទិន្នន័យនោះត្រូវបានធ្វើជាអនាមិក (ពោលគឺ មិនមានផ្ទុកព័ត៌មានផ្ទាល់ខ្លួន) និងក្នុងករណីដែលចាំបាច់ដើម្បីសម្រេចបាននូវគោលដៅស្រាវជ្រាវរបស់យើង ឬដើម្បីផ្ទៀងផ្ទាត់ការរកឃើញផ្នែកវិទ្យាសាស្ត្រតែប៉ុណ្ណោះ។ ជាពិសេស យើងអាចនឹងចែករំលែកទិន្នន័យដែលបានធ្វើជាអនាមិកនៅពេលណាមួយក្នុងពេលអនាគត ជាមួយអ្នកស្រាវជ្រាវផ្សេងទៀត សម្រាប់គោលបំណងស្រាវជ្រាវការអប់រំបែបមិនរកប្រាក់ចំណេញ។ រាល់អ្នកស្រាវជ្រាវការអប់រំពីភាគីទីបីដែលស្នើសុំប្រើប្រាស់ទិន្នន័យ ឡៃហ្វាម នឹងត្រូវឆ្លងកាត់ការពិនិត្យផ្ទៃក្នុង និងត្រូវបានវាយតម្លៃក្រោមស្តង់ដារសីលធម៌ និងសន្តិសុខដែលមានស្រាប់របស់យើង។ ដោយសារតែស្តង់ដារនៃការបោះពុម្ពផ្សាយសម្រាប់ការផលិតឡើងវិញនូវលទ្ធផលវិទ្យាសាស្ត្រ ទិន្នន័យអនាមិកដែលត្រូវបានប្រើប្រាស់សម្រាប់ការស្រាវជ្រាវការអប់រំ អាចនឹងត្រូវដាក់បញ្ចូលទៅក្នុងឃ្លាំងផ្ទុកទិន្នន័យសាធារណៈ។ ច្បាប់ចម្លងនៃទិន្នន័យលាក់អត្តសញ្ញាណដែលមិនទាន់ផ្សព្វផ្សាយជាសាធារណៈ អាចត្រូវបានចែករំលែកជាមួយអ្នកស្រាវជ្រាវការសិក្សាសម្រាប់គោលបំណងស្រាវជ្រាវមិនមែនពាណិជ្ជកម្ម ក្រោមអាជ្ញាប័ណ្ណប្រើប្រាស់តែម្តង ដែលមានកំណត់ពេល និងរក្សាការសម្ងាត់។ ប្រសិនបើការប្រើប្រាស់ស្រាវជ្រាវផ្នែកអប់រំរួមមានការប្រើប្រាស់រូបថតដែលបានផ្ទុកឡើងទៅ ឡៃហ្វាម លក្ខណៈដែលអាចសម្គាល់អត្តសញ្ញាណ និងបង្ហាញព័ត៌មានផ្ទាល់ខ្លួន (ឧទាហរណ៍ មុខមនុស្ស) នឹងត្រូវធ្វើឱ្យព្រាល ចេញពីរូបថត មុនពេលដែលវាត្រូវបានចែករំលែក។ + +យើងមិនចែករំលែក_ព័ត៌មានផ្ទាល់ខ្លួន_ណាមួយទៅកាន់សេវាកម្មវិភាគរបស់ភាគីទីបី ដូចជា ប្រព័ន្ធវិភាគទិន្នន័យហ្គូហ្គលអាណាលីទិកឡើយ។ តាមរយៈពិធីការសន្តិសុខរបស់យើង យើងការពារភាពងាយរងគ្រោះនៃព័ត៌មានផ្ទាល់ខ្លួននៅក្នុងគេហទំព័រ ឡៃហ្វាម ហើយយើងប្រើប្រាស់ពិធីការធ្វើឱ្យអាសយដ្ឋាន IP ទៅជាអនាមិក ដើម្បីការពារការកំណត់អត្តសញ្ញាណ និងទីតាំងភូមិសាស្ត្រដោយភាគីទីបី។ + +**តើយើងប្រើប្រាស់ឃុកឃីដោយរបៀបណា?** + +នៅក្នុងផ្នែកខ្លះនៃគេហទំព័ររបស់យើង ឃុកឃី អាចនឹងត្រូវដាក់នៅលើកុំព្យូទ័រ ឬឧបករណ៍របស់អ្នក។ ឃុកឃី គឺជាឯកសារតូចមួយដែលរក្សាទុកនៅលើកុំព្យូទ័រ ឬក្នុងថាសរឹងនៃឧបករណ៍របស់អ្នក ដែលវាអនុញ្ញាតឱ្យយើងអាចលើកកម្ពស់គុណភាពនៃការចូលទស្សនាគេហទំព័ររបស់យើង តាមរយៈការឆ្លើយតបទៅកាន់រូបអ្នកជាបុគ្គលម្នាក់ៗ។ យើងប្រើប្រាស់ឃុកឃី ដើម្បីកំណត់អត្តសញ្ញាណថាតើទំព័រណាខ្លះកំពុងត្រូវបានប្រើប្រាស់ និងដើម្បីកែលម្អគេហទំព័ររបស់យើង។ យើងប្រើប្រាស់ព័ត៌មាននេះសម្រាប់តែគោលបំណងវិភាគស្ថិតិប៉ុណ្ណោះ ពួកវាមិនត្រូវបានចែករំលែកជាមួយគេហទំព័រផ្សេងទៀតឡើយ ហើយក៏មិនត្រូវបានប្រើប្រាស់សម្រាប់ការផ្សាយពាណិជ្ជកម្មដែរ។ អ្នកអាចជ្រើសរើសយល់ព្រម ឬបដិសេធឃុកឃីបាន។ កម្មវិធីរុករកគេហទំព័រភាគច្រើនទទួលយកឃុកឃីដោយស្វ័យប្រវត្តិ ប៉ុន្តែជាទូទៅអ្នកអាចកែប្រែការកំណត់កម្មវិធីរុករករបស់អ្នកដើម្បីបដិសេធឃុកឃីបាន ប្រសិនបើអ្នកចង់។ ទោះជាយ៉ាងណាក៏ដោយ ប្រសិនបើអ្នកជ្រើសរើសបដិសេធឃុកឃីពី ឡៃហ្វាម នោះមុខងារនានា រួមទាំងសមត្ថភាពរបស់អ្នកក្នុងការចូលប្រើប្រាស់ និងការប្រើប្រាស់កម្មវិធី អាចនឹងត្រូវរំខាន ឬថយចុះ។ ការបន្តចូលប្រើប្រាស់គេហទំព័ររបស់យើងដោយមិនបានកែតម្រូវការកំណត់កម្មវិធីរុករករបស់អ្នក ត្រូវបានចាត់ទុកថាជាការយល់ព្រមទទួលយកឃុកឃី។ + +**តើយើងរក្សាទុកទិន្នន័យរបស់អ្នកនៅឯណា?** + +កម្មវិធីរបស់យើងត្រូវបានដំណើរការនៅលើ កម្មវិធី​ Digital Ocean ដើម្បីបម្រើសេវាកម្មគេហទំព័ររបស់យើងដល់មនុស្សចំនួនច្រើនដែលមិនអាចប៉ាន់ស្មានទុកជាមុនបាន ប្រកបដោយភាពរហ័សរហួន និងគួរឱ្យទុកចិត្ត។ នេះមានន័យថា ទិន្នន័យរបស់អ្នកអាចនឹងត្រូវរក្សាទុកនៅក្នុងមជ្ឈមណ្ឌលទិន្នន័យ និងទីតាំងជាច្រើននៅក្នុងប្រទេសកាណាដា និងសហរដ្ឋអាមេរិក (USA)។ ខណៈពេលដែលកម្មវិធីរបស់យើងមិនមានលក្ខណៈពាណិជ្ជកម្ម យើងសូមបញ្ជាក់ថា Digital Ocean គឺជាអ្នកចូលរួមក្នុងកម្មវិធី ប្រាយវេសុីសៀល​ ដែលបានអភិវឌ្ឍដោយក្រសួងពាណិជ្ជកម្មសហរដ្ឋអាមេរិក និងសហភាពអឺរ៉ុប (EU) ហើយផ្តល់សេវាកម្មសម្រាប់ការអនុលោមតាមបទប្បញ្ញត្តិការពារទិន្នន័យទូទៅរបស់សហភាពអឺរ៉ុប (GDPR)។ បន្ថែមពីលើការផ្ទុកទិន្នន័យលើកម្មវិធីក្លៅរបស់យើង ច្បាប់ចម្លងក្នុងស្រុកនៃមូលដ្ឋានទិន្នន័យ ឡៃហ្វាម ត្រូវបានរក្សាទុកនៅលើម៉ាស៊ីនមេដែលបានអ៊ិនគ្រីប និងការពារដោយពាក្យសម្ងាត់ នៅសាកលវិទ្យាល័យ ប្រីទិស កូឡុំបៀ។ ច្បាប់ចម្លងបែបអនាមិកនៃមូលដ្ឋានទិន្នន័យ ឡៃហ្វាម អាចត្រូវបានរក្សាទុកនៅក្នុងឃ្លាំងផ្ទុកទិន្នន័យសាធារណៈ ដោយអនុលោមទៅតាមស្តង់ដារបោះពុម្ពផ្សាយសម្រាប់ការផលិតឡើងវិញនូវលទ្ធផលវិទ្យាសាស្ត្រ។ + +កសិករដែលចូលរួមក្នុងបណ្តាញវិញ្ញាបនប័ត្រ អាចជ្រើសរើសទាញយកទិន្នន័យដែលពួកគេបានបញ្ចូលទៅក្នុង ឡៃហ្វាម ទៅជាទម្រង់របាយការណ៍ដែលអាចទាញយកបាន ដើម្បីចែករំលែកជាមួយភាគីខាងក្រៅ (ឧទាហរណ៍៖ អង្គភាពផ្តល់វិញ្ញាបនបត្រកសិកម្ម)។ អង្គភាពផ្តល់វិញ្ញាបនបត្រខ្លះអាចនឹងសួរ សំណួរបន្ថែមដាច់ដោយឡែកពីកសិករ ពាក់ព័ន្ធនឹងដំណើរការផ្តល់វិញ្ញាបនបត្ររបស់ពួកគេ ដែលកសិករអាចជ្រើសរើសឆ្លើយ ឬមិនឆ្លើយក៏បាន ដែលជាផ្នែកមួយនៃការទាញយកទិន្នន័យវិញ្ញាបនបត្ររបស់ពួកគេនៅក្នុងកម្មវិធី ឡៃហ្វាម។ ដើម្បីសម្របសម្រួលដល់ការរួមបញ្ចូលសំណួរពីអង្គភាពផ្តល់វិញ្ញាបនបត្រឯករាជ្យ ឡៃហ្វាម មានប្រព័ន្ធភ្ជាប់ជាមួយ សឺវេស្តេក ដែលជាប្រព័ន្ធកម្រងសំណួរស្ទង់មតិបែបប្រភពបើកចំហ និងអាចចូលប្រើប្រាស់បានដោយសេរី។ តាមរយៈការយល់ព្រមលើគោលការណ៍ឯកជនភាពនេះ អ្នកមិនត្រូវបានតម្រូវឱ្យប្រើប្រាស់មុខងារភ្ជាប់ជាមួយ សឺវេស្តេក ឡើយ។ នេះគ្រាន់តែជាមុខងារជម្រើសមួយដើម្បីសម្របសម្រួលដំណើរការផ្តល់វិញ្ញាបនបត្ររវាងកសិដ្ឋានរបស់អ្នក និងអង្គភាពផ្តល់វិញ្ញាបនបត្ររបស់អ្នកប៉ុណ្ណោះ។ + +ទិន្នន័យដែលបានបញ្ចូលតាមរយៈការភ្ជាប់ជាមួយ សឺវេស្តេក ត្រូវបានរក្សាទុកនៅលើហេដ្ឋារចនាសម្ព័ន្ធរបស់ សឺវេស្តេក ដោយប្រើប្រាស់ MongoDB នៅលើសេវាគេហទំព័រ Amazon (AWS) តាមរយៈសេវាកម្មប្រព័ន្ធ​ក្លៅអាត្លាស​ MongoDB។ សឺវេស្តេក មានគោលបំណងបង្កើតប្រព័ន្ធអេកូឡូស៊ីទិន្នន័យបើកចំហ។ ដូច្នេះ ទិន្នន័យដែលបានដាក់ស្នើទាំងអស់នៅលើវេទិកានេះ តាមលំនាំដើមគឺជាសាធារណៈ លើកលែងតែទិន្នន័យដែលភ្ជាប់ជាមួយវាលសំណួរអង្កេតដែលបានកំណត់ថាជាឯកជន ដែលអាចចូលមើលបានតែដោយអ្នកដែលកំពុងបំពេញសំណួរអង្កេត និងអ្នកបង្កើតសំណួរអង្កេតប៉ុណ្ណោះ (ឧទាហរណ៍ អ្នកផ្តល់វិញ្ញាបនបត្រ)។ អង្គភាពផ្តល់វិញ្ញាបនបត្រត្រូវបានលើកទឹកចិត្តឱ្យកំណត់ការស្ទង់មតិរបស់ពួកគេជាឯកជន ប៉ុន្តែក្រុមការងារ ឡៃហ្វាម មិនមានការគ្រប់គ្រងលើការសម្រេចចិត្តរបស់ពួកគេឡើយ។ + +**តើយើងការពារទិន្នន័យរបស់អ្នកដោយរបៀបណា?** + +យើងអនុវត្តតាមវិធីសាស្ត្រល្អបំផុតក្នុងឧស្សាហកម្មបច្ចេកវិទ្យា ដើម្បីការពារទិន្នន័យអ្នកប្រើប្រាស់ ហើយយើងបានបង្កើត និងបន្តថែទាំកម្មវិធី ឡៃហ្វាម ឱ្យស្របតាមស្តង់ដារផ្ទៀងផ្ទាត់សុវត្ថិភាពកម្មវិធី កម្រិតទី 2 របស់គម្រោងសុវត្ថិភាពកម្មវិធីគេហទំព័របើកចំហ។ ការចូលប្រាស់មូលដ្ឋានទិន្នន័យ ឡៃហ្វាម ត្រូវបានកំណត់ចំពោះតែសមាជិកនៃក្រុមការងារ ឡៃហ្វាម ណាដែលបានឆ្លងកាត់ការបណ្តុះបណ្តាលផ្នែកសីលធម៌ (សេចក្តីថ្លែងការណ៍គោលនយោបាយក្រុមប្រឹក្សាទាំងបី៖ ការអនុវត្តសីលធម៌សម្រាប់ការស្រាវជ្រាវដែលពាក់ព័ន្ធនឹងមនុស្ស, TCPS2) និងបានចុះហត្ថលេខាលើកិច្ចព្រមព្រៀងរក្សាការសម្ងាត់រួចរាល់ប៉ុណ្ណោះ។ ទោះជាយ៉ាងណាក៏ដោយ យើងមិនអាចធានាថាទិន្នន័យដែលបានបញ្ជូនតាមអ៊ីនធឺណិតនឹងមានសុវត្ថិភាពជានិច្ចនោះទេ។ ជាលទ្ធផល ថ្វីបើដ្បិតយើងខិតខំប្រឹងប្រែងការពារព័ត៌មានផ្ទាល់ខ្លួនរបស់អ្នកក៏ដោយ ក៏យើងមិនអាចធានាបានទាំងស្រុងនូវសុវត្ថិភាពនៃព័ត៌មានណាមួយដែលអ្នកបញ្ជូនមក ក្នុងកំឡុងពេលប្រើប្រាស់ ឡៃហ្វាម នោះដែរ។ + +**តើមានហានិភ័យសក្តានុពលអ្វីខ្លះទៀតដែលពាក់ព័ន្ធនឹងការប្រើប្រាស់ ឡៃហ្វាម?** + +ខណៈពេលដែលយើងបានខិតខំប្រឹងប្រែងអស់ពីសមត្ថភាព ដើម្បីធានាថាកម្មវិធីរបស់យើងមានសុវត្ថិភាព និងផ្តល់ព័ត៌មានដែលត្រឹមត្រូវបំផុតតាមដែលអាចធ្វើទៅបាន ដើម្បីជួយអ្នកក្នុងការគ្រប់គ្រងកសិដ្ឋាន យើងក៏ទទួលស្គាល់ផងដែរថា ការប្រើប្រាស់ ឡៃហ្វាម អាចនាំមកនូវហានិភ័យដល់អ្នក និងប្រតិបត្តិការកសិកម្មរបស់អ្នក ហើយវាអាចនឹងមានកំហុសឆ្គង ឬភាពមិនត្រឹមត្រូវនៃមាតិកា ព្រមទាំងហានិភ័យផ្នែកសន្តិសុខ។ ហានិភ័យដែលពាក់ព័ន្ធទាំងនេះ រួមមាន ការខាតបង់សក្តានុពលនៃផលិតកម្ម ចំណូល ឬប្រាក់ចំណេញ, ភាពមិនអាចប្រើប្រាស់បាន, ការរំខាន ឬការយឺតយ៉ាវនៃសេវាកម្ម, ការបាត់បង់ ការខូចខាត ការពុករលួយ ឬការស្តារទិន្នន័យឡើងវិញ ឬការបំពានលើទិន្នន័យ ឬសន្តិសុខប្រព័ន្ធ ដែលអាចបណ្តាលមកពីការប្រើប្រាស់កម្មវិធី ឡៃហ្វាម។ យើងមិនទទួលខុសត្រូវចំពោះហានិភ័យទាំងនេះឡើយ។ ប្រសិនបើអ្នកមានការបារម្ភ ហើយមិនអាចយល់ព្រមចំពោះលទ្ធភាពនៃការកើតឡើងនៃបញ្ហាទាំងនេះទេ សូមកុំចុះហត្ថលេខាលើទម្រង់យល់ព្រមនៅផ្នែកខាងក្រោមនៃទំព័រនេះ ឬកុំចុះឈ្មោះប្រើប្រាស់កម្មវិធីនេះអី។ នៅក្នុងករណីដែលដឹងមុនអំពីហានិភ័យដែលជិតកើតមាន (ដូចជាកាលបរិច្ឆេទដែលដឹងមុននៃការផ្អាកសេវាកម្ម) យើងនឹងខិតខំប្រឹងប្រែងឱ្យអស់ពីលទ្ធភាពដើម្បីព្រមានអ្នកជាមុនក្នុងនាមជាអ្នកប្រើប្រាស់ ដើម្បីឱ្យអ្នកអាចចាត់វិធានការបង្ការចាំបាច់នានាក្នុងការកាត់បន្ថយហានិភ័យ (ឧទាហរណ៍៖ ការចម្លងទុកទិន្នន័យរបស់អ្នក)។ + +**តើយើងនឹងរក្សាទុកទិន្នន័យរបស់អ្នករយៈពេលប៉ុន្មាន?** + +យើងមានគោលបំណងរក្សាទុកទិន្នន័យរបស់អ្នកដោយគ្មានកំណត់ ដើម្បីជាប្រយោជន៍ដល់ការផលិតឡើងវិញនូវលទ្ធផលវិទ្យាសាស្ត្រ ប៉ុន្តែការរក្សាទុកនេះនឹងមានរយៈពេលយ៉ាងហោចណាស់ 5 ឆ្នាំ។ + +**តើសិទ្ធិរបស់អ្នកមានអ្វីខ្លះទាក់ទងនឹងព័ត៌មានផ្ទាល់ខ្លួនរបស់អ្នក?** + +អ្នកមានសិទ្ធិដឹងថាតើយើងមានទិន្នន័យអ្វីខ្លះអំពីអ្នក, ស្នើសុំច្បាប់ចម្លងនៃទិន្នន័យនោះ, ធ្វើបច្ចុប្បន្នភាព និងកែតម្រូវទិន្នន័យរបស់អ្នក, ស្នើសុំឱ្យយើងបញ្ឈប់ការប្រមូលទិន្នន័យរបស់អ្នក, ស្នើសុំផ្ទេរទិន្នន័យរបស់អ្នក ឬសាកសួរ សំណួរអំពីការវិភាគណាមួយដែលប្រើប្រាស់ទិន្នន័យរបស់អ្នក។ សម្រាប់ព័ត៌មាន ឬការស្នើសុំបែបនេះ សូមទាក់ទងមកកាន់ litefarm.team@ubc.ca។ + +ការប្រើប្រាស់​ឡៃហ្វាម របស់អ្នកគឺផ្អែកលើការស្ម័គ្រចិត្តទាំងស្រុង។ ប្រសិនបើអ្នកសម្រេចចិត្តប្រើប្រាស់ ឡៃហ្វាម អ្នកអាចជ្រើសរើសបិទគណនីរបស់អ្នកនៅពេលណាក៏បាន ដោយមិនបាច់ផ្តល់ហេតុផល និងមិនបាច់មានចំណាត់ការបន្ថែមណាមួយពីអ្នកស្រាវជ្រាវឡើយ។ ប្រសិនបើអ្នកចង់លុបទិន្នន័យរបស់អ្នកទាំងអស់ចេញពីមូលដ្ឋានទិន្នន័យ ឡៃហ្វាម អ្នកអាចធ្វើបានដោយផ្ញើអ៊ីមែលស្នើសុំទៅកាន់ litefarm.team@ubc.ca។ + +**តើមានអ្វីកើតឡើងប្រសិនបើអ្នកដកការយល់ព្រមវិញ?** + +ប្រសិនបើអ្នកដកការយល់ព្រមរបស់អ្នកវិញដោយផ្ញើអ៊ីមែលទៅកាន់ litefarm.team@ubc.ca គណនីរបស់អ្នកនៅលើប្រព័ន្ធ ឡៃហ្វាម នឹងត្រូវកំណត់ថា "មិនដំណើរការ" ហើយអ្នកនឹងមិនអាចប្រើប្រាស់ប្រព័ន្ធ ឡៃហ្វាម បានទៀតឡើយ។ ទោះជាយ៉ាងណាក៏ដោយ ព័ត៌មានរបស់អ្នកនឹងមិនត្រូវបានលុបចោលឡើយ ក្នុងករណីដែលអ្នកចង់ត្រឡប់មកប្រើប្រាស់វិញនៅពេលក្រោយ។ អ្នកអាចស្នើសុំឱ្យលុបទិន្នន័យរបស់អ្នកជាអចិន្ត្រៃយ៍ និងមិនអាចប្រកែកបាន ដោយផ្ញើសំណើទៅកាន់ litefarm.team@ubc.ca។ ប្រសិនបើអ្នកមានគម្រោងដកការយល់ព្រម ហើយចង់បានច្បាប់ចម្លងនៃទិន្នន័យរបស់អ្នក សូមធ្វើការស្នើសុំវាក្នុងពេលតែមួយនៅពេលដែលអ្នកដកការយល់ព្រម។ + +**តើយើងធ្វើការផ្លាស់ប្តូរលើគោលការណ៍ឯកជនភាពដោយរបៀបណា?** + +ទោះបីជាការផ្លាស់ប្តូរភាគច្រើនអាចជាការកែប្រែបន្តិចបន្តួចក៏ដោយ ឡៃហ្វាម អាចនឹងផ្លាស់ប្តូរគោលការណ៍ឯកជនភាពរបស់ខ្លួនម្តងកាល។ យើងនឹងបង្ហោះកំណែទម្រង់ដែលបានធ្វើបច្ចុប្បន្នភាព និងកែសម្រួលនៃគោលការណ៍ឯកជនភាពនៅលើគេហទំព័រ ឡៃហ្វាម (www.litefarm.org) ហើយនឹងជូនដំណឹងដល់អ្នកតាមរយៈកម្មវិធី នៅពេលដែលយើងធ្វើការផ្លាស់ប្តូរណាមួយ។ អ្នកនឹងត្រូវតម្រូវឱ្យទទួលយកទម្រង់យល់ព្រមថ្មី ដើម្បីបន្តប្រើប្រាស់កម្មវិធីកុំព្យូទ័រនេះ។ បើអ្នកមិនទទួលយកការផ្លាស់ប្តូរទេ អ្នកនឹងអាចទាញយកទិន្នន័យរបស់អ្នកបាន ប៉ុន្តែមិនអាចបញ្ចូលទិន្នន័យថ្មីណាមួយទៅក្នុងកម្មវិធីបានទេ។ ការកែសម្រួលទាំងឡាយនឹងមានប្រសិទ្ធភាពភ្លាមៗបន្ទាប់ពីការបង្ហោះផ្សាយ។ ការបន្តប្រើប្រាស់គេហទំព័រនេះរបស់អ្នក បន្ទាប់ពីមានការផ្លាស់ប្តូរណាមួយនៅក្នុងគោលការណ៍ឯកជនភាពនេះ នឹងចាត់ទុកថាជាការយល់ព្រមរបស់អ្នកចំពោះការផ្លាស់ប្តូរនោះ។ + +**តើយើងនឹងទាក់ទងអ្នកនៅពេលណា?** + +ប្រសិនបើអ្នកបង្កើតគណនី ឡៃហ្វាម យើងនឹងផ្ញើអ៊ីមែលម្តងកាលដើម្បីប្រកាសអំពីមុខងារថ្មីៗនៅក្នុង ឡៃហ្វាម, ពន្យល់អំពីការផ្លាស់ប្តូរណាមួយចំពោះកម្មវិធី, អញ្ជើញអ្នកទៅចូលរួមព្រឹត្តិការណ៍ពិសេសៗ ឬប្រាប់អ្នកអំពីគម្រោងស្រាវជ្រាវដែលទិន្នន័យ ឡៃហ្វាម កំពុងជួយជ្រោមជ្រែងឱ្យលេចចេញជារូបរាង។ យើងក៏អាចនឹងផ្ញើអ៊ីមែលទៅអ្នកម្តងកាលផងដែរ ដើម្បីសុំមតិកែលម្អរបស់អ្នកអំពីប្រព័ន្ធ ឬគេហទំព័រនេះ។ ការចូលរួមរបស់អ្នកក្នុងការឆ្លើយតបតាមការស្នើសុំបែបនេះ គឺផ្អែកលើជម្រើសស្ម័គ្រចិត្តទាំងស្រុង ហើយនឹងមិនប៉ះពាល់ដល់ការប្រើប្រាស់ប្រព័ន្ធរបស់អ្នកឡើយ។ + +**អាជ្ញាបណ្ណ** + +នាពេលបច្ចុប្បន្ននេះ កម្មវិធី ឡៃហ្វាម គឺអាចប្រើប្រាស់បានដោយមិនគិតថ្លៃ។ កម្មវិធីកុំព្យូទ័រនេះផ្ទាល់ ត្រូវបានផ្តល់អាជ្ញាបណ្ណក្រោម អាជ្ញាប័ណ្ណសាធារណៈ វី​3​​ GNU ដែលជាអាជ្ញាបណ្ណមិនគិតថ្លៃ និងជាប្រភពបើកចំហ (https://www.gnu.org/licenses/quick-guide-gplv3.en.html) + +**សម្រាប់ព័ត៌មានបន្ថែម** + +ពាក់ព័ន្ធនឹងកម្មវិធី សូមទាក់ទង៖ + +អ្នកគ្រប់គ្រងផលិតផល៖ litefarm.team@ubc.ca + +ពាក់ព័ន្ធនឹងការសិក្សាស្រាវជ្រាវនេះ សូមទាក់ទងអ្នកស្រាវជ្រាវចម្បង៖ + +អ្នកស្រាវជ្រាវចម្បង៖ បណ្ឌិត ហាណា វីតមែន (hannah.wittman@ubc.ca) + +**ប្រសិនបើអ្នកមានការបារម្ភ ឬការត្អូញត្អែរណាមួយអំពីសិទ្ធិរបស់អ្នកក្នុងនាមជាអ្នកចូលរួមការស្រាវជ្រាវ និង/ឬបទពិសោធន៍របស់អ្នកខណៈពេលកំពុងចូលរួមក្នុងការសិក្សានេះ** + +សូមទាក់ទងទៅកាន់ខ្សែទូរស័ព្ទទទួលបណ្តឹងរបស់អ្នកចូលរួមការស្រាវជ្រាវនៅក្នុងការិយាល័យសីលធម៌ស្រាវជ្រាវរបស់ UBC តាមរយៈលេខ 604-822-8598 ឬប្រសិនបើពីចម្ងាយតាមរយអ៊ីមែល RSIL@ors.ubc.ca ឬហៅទូរសព្ទដោយឥតគិតថ្លៃទៅកាន់លេខ 1-877-822-8598។ + +**ការយល់ព្រម** + +ដោយចុចប៊ូតុង "យល់ព្រម" នៅខាងក្រោម វាបង្ហាញថាអ្នកបានទាញយកច្បាប់ចម្លងនៃទម្រង់យល់ព្រម និងគោលការណ៍ឯកជនភាពនេះទុកជាឯកសារផ្ទាល់ខ្លួនរបស់អ្នករួចរាល់ហើយ និងបង្ហាញថាអ្នកយល់ព្រមចូលរួមក្នុងការសិក្សាស្រាវជ្រាវនេះ។ + +លេខសម្គាល់សីលធម៌នៃការសិក្សារបស់ UBC៖ H19-01482 diff --git a/packages/webapp/src/containers/Consent/locales/km/Worker.Consent.md b/packages/webapp/src/containers/Consent/locales/km/Worker.Consent.md new file mode 100644 index 0000000000..2f02262d21 --- /dev/null +++ b/packages/webapp/src/containers/Consent/locales/km/Worker.Consent.md @@ -0,0 +1,147 @@ +##### បំណែប្រែទី 7៖ ថ្ងៃទី 12 ខែធ្នូ ឆ្នាំ 2024 + +#### ទម្រង់ការយល់ព្រមដោយបានជម្រាបជូនព័ត៌មាន និងគោលនយោបាយឯកជនភាព (កម្មករកសិដ្ឋាន) + +សូមស្វាគមន៍មកកាន់ ឡៃហ្វាម! + +យើងយល់ថា ឯកជនភាពរបស់អ្នក និងការការពារទិន្នន័យរបស់អ្នកគឺមានសារៈសំខាន់សម្រាប់អ្នក។ យើងបានបង្កើតទម្រង់បែបបទយល់ព្រមដែលបានជម្រាបជូនព័ត៌មាន និងគោលការណ៍ឯកជនភាពនេះឡើង ដើម្បីជួយអ្នកឱ្យយល់អំពីរបៀប និងពេលវេលាដែលយើងប្រមូល ប្រើប្រាស់ និងចែករំលែកព័ត៌មានរបស់អ្នក ព្រមទាំងដើម្បីធានាថា យើងទទួលបានការយល់ព្រមពីអ្នកក្នុងការធ្វើដូឆ្នោះ។ សូមចងចាំថា អ្នកនឹងត្រូវផ្តល់ការយល់ព្រមដាច់ដោយឡែកពីគ្នាសម្រាប់ការប្រមូល និងការប្រើប្រាស់ទិន្នន័យរបស់អ្នក ដូចដែលបានពិពណ៌នានៅក្នុងទម្រង់បែបបទយល់ព្រមដែលបានជម្រាបជូនព័ត៌មាន និងគោលការណ៍ឯកជនភាពនេះ **សម្រាប់រាល់ចំការទាំងអស់ដែលអ្នកមានការទាក់ទងជាមួយ តាមរយៈគណនីរបស់អ្នកនៅលើប្រព័ន្ធ ឡៃហ្វាម**។ ប្រសិនបើអ្នកមិនយល់ស្របនឹងការអនុវត្តរបស់យើង ដូចដែលបានគូសបញ្ជាក់នៅក្នុងទម្រង់បែបបទយល់ព្រមដែលបានជម្រាបជូនព័ត៌មាន និងគោលការណ៍ឯកជនភាពនេះទេ អ្នកនឹងមិនអាចប្រើប្រាស់ប្រព័ន្ធ ឡៃហ្វាម បានឡើយ។ + +#### តើអ្វីទៅជា ឡៃហ្វាម? + +ឡៃហ្វាម គឺជាគម្រោងស្រាវជ្រាវវិទ្យាសាស្ត្របែបចូលរួមមួយ ដែលរៀបចំឡើងនៅសាកលវិទ្យាល័យ ប្រីទិស កូឡុំបៀ ដើម្បីជួយកែលម្អការទទួលបានបច្ចេកវិទ្យាកសិកម្មឌីជីថលសម្រាប់សហគមន៍កសិកម្ម និងអភិវឌ្ឍការយល់ដឹងឱ្យកាន់តែប្រសើរឡើងអំពីផ្លូវឆ្ពោះទៅរកកសិកម្មប្រកបដោយនិរន្តរភាព។ សាកលវិទ្យាល័យ ប្រីទិស កូឡុំបៀ ធ្វើការជាមួយអង្គការកសិករដើម្បីសាកល្បង និងវាយតម្លៃឧបករណ៍ ព្រមទាំងចំណេះដឹង ដែលមានគោលបំណងជួយកសិករក្នុងការគ្រប់គ្រងចំការរបស់ពួកគេតាមរបៀបដែលចំណេញបានកម្រៃច្រើនជាងមុន និងមាននិរន្តរភាពទាំងផ្នែកបរិស្ថាន និងសង្គម។ កូដដែលជាមូលដ្ឋានគ្រឹះនៃ ឡៃហ្វាម គឺមិនគិតថ្លៃ និងជាប្រភពកូដចំហ (ជីភីអិល​​​វី3) ដើម្បីឱ្យអ្នកស្រាវជ្រាវ អ្នកជំនាញ និងអ្នកអភិវឌ្ឍន៍ទូទាំងពិភពលោកអាចជួយកែលម្អសេវាកម្មនានាដែលផ្តល់ជូនសហគមន៍កសិកម្ម។ ឡៃហ្វាម គឺជាអង្គភាពមិនស្វែងរកប្រាក់ចំណេញ។ + +#### នរណាខ្លះជាក្រុមការងារឡៃហ្វាម? + +ក្រុមការងារ ឡៃហ្វាម គឺជាក្រុមពហុជំនាញដែលរួមមានអ្នកវិទ្យាសាស្ត្រ អ្នកស្រាវជ្រាវ កសិករ អ្នករចនា និងអ្នកជំនាញផ្នែកកម្មវិធីកុំព្យូទ័រ។ ដំបូងឡើយ ក្រុមការងារនេះត្រូវបានបង្កើតឡើងនៅសាកលវិទ្យាល័យ ប្រីទិស កូឡុំបៀ (UBC) ហើយបានពង្រីកខ្លួនរហូតរួមបញ្ចូលទាំងបណ្តាញសកលបែបចូលរួមនៃបុគ្គល និងអង្គការនានា។ អ្នកស្រាវជ្រាវចម្បងគឺ បណ្ឌិត ហ្សៀ មេហរ៉ាប៊ី (សាកលវិទ្យាល័យ កូឡូរ៉ាដូ) និង បណ្ឌិត ហាណាក់ វីតមិន (hannah.wittman@ubc.ca) ព្រមទាំង បណ្ឌិត ស៊ន ស្មុកល័រ នាយកមជ្ឈមណ្ឌលសម្រាប់ប្រព័ន្ធស្បៀងអាហារប្រកបដោយនិរន្តរភាព នៅកសិដ្ឋាននៃសាកលវិទ្យាល័យ ប្រីទិស កូឡុំបៀ។ + +#### តើអ្នកណាជាអ្នកផ្តល់មូលនិធិដល់ ឡៃហ្វាម? + +ឡៃហ្វាម ត្រូវបានផ្តល់មូលនិធិដោយមជ្ឈមណ្ឌលសម្រាប់ប្រព័ន្ធស្បៀងអាហារប្រកបដោយនិរន្តរភាពនៅ សាកលវិទ្យាល័យ ប្រីទិស កូឡុំបៀ និងជំនួយឥតសំណងផ្សេងៗទៀត។ សម្រាប់បញ្ជីឈ្មោះពេញលេញ សូមចូលទៅកាន់៖ https://ubcfarm.ubc.ca/csfs-research/litefarm/។ ម្ចាស់ជំនួយខាងក្រៅរបស់យើងមិនមានសិទ្ធិសម្រេចក្នុងការប្រតិបត្តិការ និងការគ្រប់គ្រងរបស់ ឡៃហ្វាម ឡើយ ហើយពួកគេមិនអាចចូលប្រើប្រាស់ព័ត៌មានផ្ទាល់ខ្លួនណាមួយដែលរក្សាទុកនៅលើប្រព័ន្ធនេះបានទេ។ គំរូមូលនិធិរបស់យើងនាពេលបច្ចុប្បន្នគឺផ្អែកលើអ្នកបរិច្ចាគ និងជំនួយឥតសំណង។ + +#### ហេតុអ្វីបានជាយើងដំណើរការគម្រោងនេះ? + +យើងកត់សម្គាល់ឃើញនូវកង្វះខាតក្នុងការទទួលបានសេវាបច្ចេកវិទ្យាឌីជីថលរបស់កសិករ អត្រានៃការយកទៅប្រើប្រាស់នៅមានកម្រិតទាប និងតម្រូវការដែលបានលើកឡើងដោយកសិករក្នុងការបញ្ចូលគ្នានូវសេវាក្របគ្រងទិន្នន័យកសិកម្មជាច្រើន ទៅក្នុងប្រព័ន្ធតែមួយដែលមិនមែនដើម្បីគោលបំណងពាណិជ្ជកម្ម។ យើងចង់បង្កើតដំណោះស្រាយមួយដែលជួយកសិករក្នុងការដំណើរការអាជីវកម្មរបស់ពួកគេតាមរបៀបដែលមាននិរន្តរភាពជាងមុន ទាំងផ្នែកហិរញ្ញវត្ថុ និងប្រព័ន្ធអេកូឡូស៊ី ព្រមទាំងជួយជំរុញវិទ្យាសាស្ត្រនៃនិរន្តរភាពឱ្យកាន់តែរីកចម្រើនផងដែរ។ + +#### តើទិន្នន័យអ្វីខ្លះដែលយើងប្រមូល? + +អាស្រ័យលើផ្នែកណាមួយនៃប្រព័ន្ធ ឡៃហ្វាម ដែលអ្នកប្រើប្រាស់ យើងអាចនឹងប្រមូលព័ត៌មានប្រភេទផ្សេងៗគ្នា៖ + +**ព័ត៌មានផ្ទាល់ខ្លួន** + +"ព័ត៌មានផ្ទាល់ខ្លួន" សំដៅលើព័ត៌មានណាមួយដែលអាចប្រើប្រាស់ដើម្បីសម្គាល់អត្តសញ្ញាណរបស់អ្នក។ ឡៃហ្វាម នឹងមិនលាតត្រដាងព័ត៌មានផ្ទាល់ខ្លួនទៅកាន់ភាគីទីបីឡើយ ប្រសិនបើគ្មានការយល់ព្រមច្បាស់លាស់ពីអ្នក។ ចំណុចនេះរួមបញ្ចូលទាំង៖ + +- ព័ត៌មានទំនាក់ទំនង (ឈ្មោះ, អាសយដ្ឋាន, លេខទូរស័ព្ទ, អាសយដ្ឋានអ៊ីមែល) + +- ព័ត៌មានប្រជាសាស្ត្រ (ភេទ, ឆ្នាំកំណើត, ភាសាដែលពេញចិត្ត, ប្រទេស, រូបិយប័ណ្ណ) + +- រូបថត + +- អាសយដ្ឋានពិធីការអ៊ីនធឺណិត (IP) + +- ទីតាំងភូមិសាស្ត្រ (ឧទាហរណ៍៖ កូអរដោនេ ជីភីអែស នៃទីតាំងកសិដ្ឋាន ព្រំប្រទល់ទីតាំង ។ល។) + +**ព័ត៌មានគ្រប់គ្រងចំការ៖** + +ឡៃហ្វាម ប្រើប្រាស់ព័ត៌មានគ្រប់គ្រងដែលអ្នកបានបញ្ចូលទៅក្នុងកម្មវិធី ដើម្បីបង្កើតជាការយល់ដឹងស៊ីជម្រៅអំពីអត្ថប្រយោជន៍ ឬផលប៉ះពាល់ផ្នែកហិរញ្ញវត្ថុ បរិស្ថាន និងសង្គម នៃការសម្រេចចិត្តគ្រប់គ្រងរបស់អ្នក។ យើងធ្វើការលាក់អត្តសញ្ញាណទិន្នន័យនេះ ដើម្បីដំណើរការស្រាវជ្រាវការសិក្សាបែបមិនរកប្រាក់ចំណេញអំពីប្រព័ន្ធស្បៀងអាហារប្រកបដោយនិរន្តរភាព។ ដោយសារតែទិន្នន័យនេះត្រូវបានលាក់អត្តសញ្ញាណនៅពេលយកទៅប្រើប្រាស់ក្នុងការស្រាវជ្រាវរបស់យើង វាមិនអាចស្វែងរកដានត្រឡប់មករកអ្នក ឬចំការរបស់អ្នកវិញបានឡើយ។ ទិន្នន័យនេះរួមបញ្ចូលទាំង៖ + +- ព័ត៌មានអំពីកិច្ចការដែលអ្នកបានធ្វើនៅក្នុងចំការ៖ រយៈពេល, ទីតាំង, ដំណាំដែលរងផលប៉ះពាល់, វត្ថុធាតុដើម, កំណត់សម្គាល់, កាលបរិច្ឆេទ, ស្ថានភាពនៃការបញ្ចប់កិច្ចការ ជាដើម។ + +- ព័ត៌មានគ្រប់គ្រងសត្វល្អិតចង្រៃ៖ ឈ្មោះផលិតផល, បរិមាណផលិតផលដែលបានប្រើ, គោលដៅនៃការប្រើប្រាស់ (ពោលគឺ ឈ្មោះសត្វល្អិតចង្រៃ ឬជំងឺ), ឈ្មោះទូទៅ, ឈ្មោះវិទ្យាសាស្ត្រ, ក្រុម, ឈ្មោះសារធាតុសកម្ម, កំហាប់សារធាតុសកម្ម, រយៈពេលអត់បាញ់ថ្នាំមុនប្រមូលផល, រយៈពេលផ្អាកចូលចម្ការក្រោយបាញ់ថ្នាំ, ប្រភេទនៃការគ្រប់គ្រង, ទីតាំង និងដំណាំគោលដៅ។ + +- ព័ត៌មានអំពីការប្រមូលផល៖ វាលស្រែ/ចំការដែលបានប្រមូលផល, ដំណាំដែលបានប្រមូលផល, បរិមាណដែលបានប្រមូលផល, ការប្រើប្រាស់ផលដែលប្រមូលបាន។ + +- ព័ត៌មានអំពីការសាបព្រោះ/ដាំគ្រាប់ពូជ៖ ទីតាំងដែលបានសាបព្រោះ, ដំណាំដែលបានសាបព្រោះ, ជម្រៅចន្លោះជួរ, ប្រវែង, ទទឹង និងដង់ស៊ីតេ/អត្រាដាំ។ + +- ព័ត៌មានអំពីការងារនៅក្នុងចំការ៖ ទីតាំង, ដំណាំ, ប្រភេទនៃការងារ, កំណត់សម្គាល់។ + +- ព័ត៌មានដី៖ ទីតាំង ជម្រៅ វាយនភាពដី ភាគរយនៃប៉ូតាស្យូម ផូស្វ័រ អាសូត សារធាតុសរីរាង្គ កាបូនសរីរាង្គ កាបូនអសរីរាង្គ កាបូនសរុប ស៊ុលហ្វួរ កាល់ស្យូម ម៉ាញេស្យូម សូដ្យូម ស័ង្កសី ម៉ង់ហ្គាណែស ដែក ទង់ដែង បូរ៉ុង សមត្ថភាពប្តូរកាចុង (CEC) កម្រិតអាស៊ីត-បាស ដង់ស៊ីតេដីសរុប។ + +- ព័ត៌មានអំពីការស្រោចស្រព៖ ទីតាំង, ដំណាំ, ប្រភេទនៃការស្រោចស្រព, អត្រាលំហូរទឹក, រយៈពេលហូរទឹកសរុប។ + +- ព័ត៌មានអំពីការចុះពិនិត្យចំការ៖ ទីតាំង, ដំណាំ, ប្រភេទ, សកម្មភាពដែលត្រូវធ្វើ (បាទ/ចាស ឬ ទេ)។ + +- ព័ត៌មានផ្សេងៗ៖ ទីតាំង, ដំណាំ, កំណត់សម្គាល់។ + +- ព័ត៌មានទាក់ទងនឹងការបញ្ចប់កិច្ចការ រួមមាន៖ កាលបរិច្ឆេទ, រយៈពេលនៃការងារ, អារម្មណ៍ (សប្បាយចិត្ត, សប្បាយចិត្តខ្លាំង, កើតទុក្ខ, កើតទុក្ខខ្លាំង, ធម្មតា), កំណត់សម្គាល់អំពីការងារ។ + +- ព័ត៌មានអំពីសត្វ៖ ឈ្មោះសត្វមួយក្បាលៗ ឬឈ្មោះសត្វជាហ្វូង, ប្រភេទ, ពូជ, ភេទ, កាលបរិច្ឆេទនាំចូល ឬថ្ងៃកើត និងព័ត៌មានលម្អិតអំពីអត្តសញ្ញាណផ្សេងទៀត + +- ព័ត៌មានអំពីការផ្លាស់ទីរបស់សត្វ៖ ទីតាំង, មូលហេតុនៃការផ្លាស់ទី និងកាលបរិច្ឆេទនៃការផ្លាស់ទី + +**ទិន្នន័យប្រើប្រាស់** + +យើងប្រមូលទិន្នន័យនៃការប្រើប្រាស់ (ពោលគឺ ស្ថិតិទូទៅអំពីអ្នកប្រើប្រាស់, ទម្រង់ចរាចរណ៍អ៊ីនធឺណិត និងរបៀបដែលអ្នកប្រើប្រាស់ឆ្លើយតបទៅនឹងមុខងារផ្សេងៗនៃគេហទំព័រ) ដើម្បីកែលម្អគុណភាពនៃសេវាកម្មដែលយើងផ្តល់ជូនអ្នក។ ទិន្នន័យប្រភេទនេះរួមមាន៖ ពេលវេលាដែលអ្នកចូលប្រើ ឡៃហ្វាម, ទំព័រដែលអ្នកស្នើសុំមើល, រយៈពេលដែលអ្នកចូលមើលគេហទំព័រ, របៀបដែលអ្នកបញ្ជាប្រើប្រាស់កម្មវិធី និងព័ត៌មានលម្អិតបច្ចេកទេសអំពីឧបករណ៍របស់អ្នក (ឧទាហរណ៍៖ កម្មវិធីរុករកគេហទំព័រ, ប្រភេទអេក្រង់ និងអង្គដំណើរការ)។ ទិន្នន័យនេះនឹងត្រូវបានភ្ជាប់ទៅនឹងឈ្មោះអ្នកប្រើប្រាស់ ឡៃហ្វាម របស់អ្នក (ប្រសិនបើអ្នកបានចូលប្រើប្រាស់កម្មវិធី) ឬភ្ជាប់ទៅនឹងអាសយដ្ឋាន IP របស់អ្នក (ប្រសិនបើអ្នកមិនបានចូលប្រើប្រាស់កម្មវិធី)។ យើងអាចនឹងប្រើប្រាស់កម្មវិធីដូចជា Google Analytics ដើម្បីប្រមូល និងវិភាគ ទិន្នន័យប្រើប្រាស់ ប៉ុន្តែនៅក្នុងករណីទាំងនេះ ព័ត៌មានផ្ទាល់ខ្លួនទាំងអស់នឹងត្រូវ លាក់អត្តសញ្ញាណ។ + +**តើយើងប្រើប្រាស់ទិន្នន័យដោយរបៀបណា?** + +ដូចដែលបានពិពណ៌នាខាងលើ យើងប្រើប្រាស់ទិន្នន័យប្រើប្រាស់របស់អ្នក (ពោលគឺ ព័ត៌មានទូទៅអំពីរបៀបដែលអ្នកធ្វើអន្តរកម្មជាមួយប្រព័ន្ធ ឡៃហ្វាម) ដើម្បីកែលម្អប្រព័ន្ធ ឡៃហ្វាម និងសេវាកម្មនានាដែលប្រព័ន្ធនេះផ្តល់ជូន។ + +ព័ត៌មានដែលអ្នកបានផ្តល់អំពីការបញ្ចប់កិច្ចការ នឹងត្រូវបានបង្ហាញជាលក្ខណៈសរុប (ដោយគ្មានព័ត៌មានដែលអាចសម្គាល់អត្តសញ្ញាណផ្ទាល់ខ្លួនឡើយ) ជូនដល់អ្នកគ្រប់គ្រងចំការ និងសម្រាប់គោលបំណងស្រាវជ្រាវ។ + +**តើយើងចែករំលែកអ្វីខ្លះ?** + +យើងនឹងចែករំលែកទិន្នន័យរបស់អ្នកជាមួយភាគីទីបី លុះត្រណាតែទិន្នន័យនោះត្រូវបានលាក់អត្តសញ្ញាណ (ពោលគឺ មិនមានព័ត៌មានផ្ទាល់ខ្លួន) និងចាំបាច់ដើម្បីសម្រេចបាននូវគោលដៅស្រាវជ្រាវរបស់យើង ឬដើម្បីផ្ទៀងផ្ទាត់ការរកឃើញផ្នែកវិទ្យាសាស្ត្រប៉ុណ្ណោះ។ ជាពិសេស យើងអាចនឹងចែករំលែកទិន្នន័យដែលបានលាក់អត្តសញ្ញាណនៅពេលណាមួយនាពេលអនាគត ជាមួយអ្នកស្រាវជ្រាវផ្សេងទៀត សម្រាប់គោលបំណងស្រាវជ្រាវការសិក្សាបែបមិនរកប្រាក់ចំណេញ។ អ្នកស្រាវជ្រាវការសិក្សាជាភាគីទីបីណាដែលស្នើសុំប្រើប្រាស់ទិន្នន័យ ឡៃហ្វាម នឹងត្រូវឆ្លងកាត់ការពិនិត្យផ្ទៃក្នុង និងត្រូវបានវាយតម្លៃក្រោមស្តង់ដារសីលធម៌ និងសន្តិសុខដែលមានស្រាប់របស់យើង។ ដោយសារតែស្តង់ដារបោះពុម្ពផ្សាយសម្រាប់ការផលិតឡើងវិញនូវលទ្ធផលវិទ្យាសាស្ត្រ ទិន្នន័យលាក់អត្តសញ្ញាណដែលត្រូវបានប្រើប្រាស់សម្រាប់ការស្រាវជ្រាវការសិក្សា អាចនឹងត្រូវដាក់ឱ្យប្រើប្រាស់នៅលើឃ្លាំងផ្ទុកទិន្នន័យសាធារណៈ។ ច្បាប់ចម្លងនៃទិន្នន័យលាក់អត្តសញ្ញាណដែលមិនទាន់ផ្សព្វផ្សាយជាសាធារណៈ អាចត្រូវបានចែករំលែកជាមួយអ្នកស្រាវជ្រាវការសិក្សាសម្រាប់គោលបំណងស្រាវជ្រាវមិនមែនពាណិជ្ជកម្ម ក្រោមអាជ្ញាប័ណ្ណប្រើប្រាស់តែម្តង ដែលមានកំណត់ពេល និងរក្សាការសម្ងាត់។ ប្រសិនបើការប្រើប្រាស់ក្នុងការស្រាវជ្រាវការសិក្សារួមមានការប្រើប្រាស់រូបថតដែលបានបង្ហោះទៅក្នុង ឡៃហ្វាម នោះរាល់ទម្រង់ដែលអាចសម្គាល់បានដែលលាតត្រដាងព័ត៌មានផ្ទាល់ខ្លួន (ឧទាហរណ៍៖ ផ្ទៃមុខរបស់មនុស្ស) នឹងត្រូវបានធ្វើឱ្យព្រាលនៅលើរូបថត មុនពេលរូបថតទាំងនោះត្រូវបានចែករំលែក។ + +យើងមិនចែករំលែក_ព័ត៌មានផ្ទាល់ខ្លួន_ណាមួយទៅកាន់សេវាកម្មវិភាគរបស់ភាគីទីបី ដូចជា ប្រព័ន្ធវិភាគទិន្នន័យហ្គូហ្គលអាណាលីទិកឡើយ។ តាមរយៈពិធីការសន្តិសុខរបស់យើង យើងការពារភាពងាយរងគ្រោះនៃព័ត៌មានផ្ទាល់ខ្លួននៅក្នុងគេហទំព័រ ឡៃហ្វាមហើយយើងប្រើប្រាស់ពិធីការលាក់អត្តសញ្ញាណ IP ដើម្បីការពារការសម្គាល់អត្តសញ្ញាណ និងទីតាំងភូមិសាស្ត្រដោយភាគីទីបី។ + +**តើយើងប្រើប្រាស់ឃុកឃី ដោយរបៀបណា?** + +នៅក្នុងផ្នែកខ្លះនៃគេហទំព័ររបស់យើង ឃុកឃី អាចនឹងត្រូវបានដាក់នៅលើកុំព្យូទ័រ ឬឧបករណ៍របស់អ្នក។ ឃុកឃី គឺជាឯកសារតូចមួយដែលរក្សាទុកនៅលើកុំព្យូទ័រ ឬក្នុងថាសរឹងនៃឧបករណ៍របស់អ្នក ដែលវាអនុញ្ញាតឱ្យយើងអាចលើកកម្ពស់គុណភាពនៃការចូលទស្សនាគេហទំព័ររបស់យើង តាមរយៈការឆ្លើយតបទៅកាន់រូបអ្នកជាបុគ្គលម្នាក់ៗ។ យើងប្រើប្រាស់ឃុកឃីដើម្បីសម្គាល់ថាតើទំព័រណាខ្លះកំពុងត្រូវបានប្រើប្រាស់ និងដើម្បីកែលម្អគេហទំព័ររបស់យើង។ យើងប្រើប្រាស់ព័ត៌មាននេះសម្រាប់តែគោលបំណងវិភាគស្ថិតិប៉ុណ្ណោះ វាមិនត្រូវបានចែករំលែកជាមួយគេហទំព័រផ្សេងទៀតឡើយ ហើយក៏មិនត្រូវបានប្រើប្រាស់សម្រាប់ផ្ទាំងផ្សាយពាណិជ្ជកម្មនោះដែរ។ អ្នកអាចជ្រើសរើសយល់ព្រមទទួលយក ឬបដិសេធឃុកឃី។ កម្មវិធីរុករកគេហទំព័រភាគច្រើនទទួលយកឃុកឃីដោយស្វ័យប្រវត្តិ ប៉ុន្តែជាទូទៅអ្នកអាចកែប្រែការកំណត់កម្មវិធីរុករករបស់អ្នកដើម្បីបដិសេធឃុកឃីបាន ប្រសិនបើអ្នកចង់។ ទោះជាយ៉ាងណាក៏ដោយ ប្រសិនបើអ្នកជ្រើសរើសបដិសេធឃុកឃីពី ឡៃហ្វាម នោះមុខងារនានា រួមទាំងសមត្ថភាពរបស់អ្នកក្នុងការចូលប្រើប្រាស់ និងការប្រើប្រាស់កម្មវិធី អាចនឹងត្រូវរំខាន ឬថយចុះ។ ការយល់ព្រមទទួលយកឃុកឃីត្រូវបានចាត់ទុកថាជាការយល់ព្រមដោយប្រយោល ប្រសិនបើអ្នកបន្តចូលប្រើប្រាស់គេហទំព័ររបស់យើងដោយមិនបានកែតម្រូវការកំណត់នៃកម្មវិធីរុករករបស់អ្នក។ + +**តើយើងរក្សាទុកទិន្នន័យរបស់អ្នកនៅឯណា?** + +កម្មវិធីរបស់យើងត្រូវបានដំណើរការនៅលើ Digital Ocean ដើម្បីបម្រើសេវាគេហទំព័ររបស់យើងបានលឿន និងគួរឱ្យទុកចិត្ត ជូនដល់មនុស្សចំនួនច្រើនដែលមិនអាចប៉ាន់ស្មានទុកជាមុនបាន។ នេះមានន័យថា ទិន្នន័យរបស់អ្នកអាចនឹងត្រូវរក្សាទុកនៅក្នុងមជ្ឈមណ្ឌលទិន្នន័យ និងទីតាំងជាច្រើន នៅក្នុងប្រទេសកាណាដា និងសហរដ្ឋអាមេរិក (USA)។ ខណៈពេលដែលកម្មវិធីរបស់យើងមិនមានលក្ខណៈពាណិជ្ជកម្ម យើងសូមបញ្ជាក់ថា Digital Ocean គឺជាអ្នកចូលរួមក្នុងកម្មវិធី ប្រាយវេសុីសៀល​ ដែលបានអភិវឌ្ឍដោយក្រសួងពាណិជ្ជកម្មសហរដ្ឋអាមេរិក និងសហភាពអឺរ៉ុប (EU) ហើយផ្តល់សេវាកម្មសម្រាប់ការអនុលោមតាមបទប្បញ្ញត្តិការពារទិន្នន័យទូទៅរបស់សហភាពអឺរ៉ុប (GDPR)។ បន្ថែមពីលើការផ្ទុកទិន្នន័យលើកម្មវិធីក្លៅរបស់យើង ច្បាប់ចម្លងក្នុងស្រុកនៃមូលដ្ឋានទិន្នន័យ ឡៃហ្វាម ត្រូវបានរក្សាទុកនៅលើម៉ាស៊ីនមេដែលបានអ៊ិនគ្រីប និងការពារដោយពាក្យសម្ងាត់ នៅសាកលវិទ្យាល័យ ប្រីទិស កូឡុំបៀ។ ច្បាប់ចម្លងដែលបានលាក់អត្តសញ្ញាណនៃមូលដ្ឋានទិន្នន័យ ឡៃហ្វាម អាចត្រូវបានរក្សាទុកនៅលើឃ្លាំងផ្ទុកទិន្នន័យសាធារណៈ ដោយអនុលោមតាមស្តង់ដារបោះពុម្ពផ្សាយសម្រាប់ការផលិតឡើងវិញនូវលទ្ធផលវិទ្យាសាស្ត្រ។ + +**តើយើងការពារទិន្នន័យរបស់អ្នកដោយរបៀបណា?** + +យើងអនុវត្តតាមវិធីសាស្ត្រល្អបំផុតក្នុងឧស្សាហកម្មបច្ចេកវិទ្យា ដើម្បីការពារទិន្នន័យអ្នកប្រើប្រាស់ ហើយយើងបានបង្កើត និងបន្តថែទាំកម្មវិធី ឡៃហ្វាម ឱ្យស្របតាមស្តង់ដារផ្ទៀងផ្ទាត់សុវត្ថិភាពកម្មវិធី កម្រិតទី 2 របស់គម្រោងសុវត្ថិភាពកម្មវិធីគេហទំព័របើកចំហ។ ការចូលប្រាស់មូលដ្ឋានទិន្នន័យ ឡៃហ្វាម ត្រូវបានកំណត់ចំពោះតែសមាជិកនៃក្រុមការងារ ឡៃហ្វាម ណាដែលបានឆ្លងកាត់ការបណ្តុះបណ្តាលផ្នែកសីលធម៌ (សេចក្តីថ្លែងការណ៍គោលនយោបាយក្រុមប្រឹក្សាទាំងបី៖ ការអនុវត្តសីលធម៌សម្រាប់ការស្រាវជ្រាវដែលពាក់ព័ន្ធនឹងមនុស្ស, TCPS2) និងបានចុះហត្ថលេខាលើកិច្ចព្រមព្រៀងរក្សាការសម្ងាត់រួចរាល់ប៉ុណ្ណោះ។ ទោះជាយ៉ាងណាក៏ដោយ យើងមិនអាចធានាបានថា ទិន្នន័យដែលបានបញ្ជូនតាមរយៈអ៊ីនធឺណិតនឹងមានសុវត្ថិភាពជានិច្ចនោះទេ។ ជាលទ្ធផល ថ្វីបើដ្បិតតែយើងខិតខំប្រឹងប្រែងដើម្បីការពារព័ត៌មានផ្ទាល់ខ្លួនរបស់អ្នកក៏ដោយ ក៏យើងមិនអាចធានាបានទាំងស្រុងនូវសន្តិសុខនៃព័ត៌មានណាមួយដែលអ្នកបញ្ជូនមក ក្នុងអំឡុងពេលប្រើប្រាស់ ឡៃហ្វាម នោះទេ។ + +**តើមានហានិភ័យសក្តានុពលអ្វីខ្លះទៀតដែលពាក់ព័ន្ធនឹងការប្រើប្រាស់ ឡៃហ្វាម?** + +ខណៈពេលដែលយើងបានខិតខំប្រឹងប្រែងអស់ពីលទ្ធភាពដើម្បីធានាថាកម្មវិធីរបស់យើងមានសុវត្ថិភាព យើងទទួលស្គាល់ថាការប្រើប្រាស់ ឡៃហ្វាម របស់អ្នក នៅតែនាំមកនូវហានិភ័យមួយចំនួនដល់ឯកជនភាពនៃព័ត៌មានផ្ទាល់ខ្លួនរបស់អ្នក (ដូចដែលបានកំណត់ខាងលើ)។ យើងមិនទទួលខុសត្រូវចំពោះហានិភ័យទាំងនេះឡើយ។ ប្រសិនបើអ្នកមានការព្រួយបារម្ភ ហើយមិនអាចយល់ព្រមចំពោះលទ្ធភាពនៃការកើតឡើងនៃហានិភ័យនេះទេ សូមកុំចុះហត្ថលេខាលើទម្រង់បែបបទយល់ព្រមនៅផ្នែកខាងក្រោមនៃទំព័រនេះ ឬកុំចុះឈ្មោះប្រើប្រាស់ផលិតផលនេះអី។ + +**តើយើងនឹងរក្សាទុកទិន្នន័យរបស់អ្នករយៈពេលប៉ុន្មាន?** + +យើងមានគោលបំណងរក្សាទុកទិន្នន័យរបស់អ្នកដោយគ្មានកំណត់ ដើម្បីជាប្រយោជន៍ដល់ការផលិតឡើងវិញនូវលទ្ធផលវិទ្យាសាស្ត្រ ប៉ុន្តែការរក្សាទុកនេះគឺយ៉ាងហោចណាស់ឱ្យបានរយៈពេល 5 ឆ្នាំ។ + +**តើសិទ្ធិរបស់អ្នកមានអ្វីខ្លះទាក់ទងនឹងព័ត៌មានផ្ទាល់ខ្លួនរបស់អ្នក?** + +អ្នកមានសិទ្ធិដឹងថាតើយើងមានទិន្នន័យអ្វីខ្លះអំពីអ្នក, ស្នើសុំច្បាប់ចម្លងនៃទិន្នន័យនោះ, ធ្វើបច្ចុប្បន្នភាព និងកែតម្រូវទិន្នន័យរបស់អ្នក, ស្នើសុំឱ្យយើងបញ្ឈប់ការប្រមូលទិន្នន័យរបស់អ្នក, ស្នើសុំផ្ទេរទិន្នន័យរបស់អ្នក ឬសាកសួរ សំណួរអំពីការវិភាគណាមួយដែលប្រើប្រាស់ទិន្នន័យរបស់អ្នក។ សម្រាប់ព័ត៌មាន ឬការស្នើសុំបែបនេះ សូមទាក់ទងមកកាន់ litefarm.team@ubc.ca។ + +**តើមានអ្វីកើតឡើងប្រសិនបើអ្នកដកការយល់ព្រមវិញ?** + +ការប្រើប្រាស់ ឡៃហ្វាម របស់អ្នកគឺផ្អែកលើការស្ម័គ្រចិត្តទាំងស្រុង។ ប្រសិនបើអ្នកសម្រេចចិត្តប្រើប្រាស់ ឡៃហ្វាម អ្នកអាចជ្រើសរើសដើម្បីបិទគណនីរបស់អ្នកនៅពេលណាក៏បាន ដោយមិនបាច់ផ្តល់មូលហេតុ និងដោយមិនចាំបាច់មានចំណាត់ការបន្ថែមណាមួយពីអ្នកស្រាវជ្រាវឡើយ។ ប្រសិនបើអ្នកចង់លុបទិន្នន័យទាំងអស់របស់អ្នកចេញពីមូលដ្ឋានទិន្នន័យ ឡៃហ្វាម អ្នកអាចធ្វើដូឆ្នោះបានតាមរយៈការផ្ញើអ៊ីមែលស្នើសុំទៅកាន់ litefarm.team@ubc.ca។ + +ប្រសិនបើអ្នកដកការយល់ព្រមរបស់អ្នកដោយការផ្ញើអ៊ីមែលទៅកាន់ litefarm.team@ubc.ca គណនីរបស់អ្នកនៅលើប្រព័ន្ធ ឡៃហ្វាម នឹងត្រូវកំណត់សម្គាល់ថា «មិនសកម្ម» ហើយអ្នកនឹងមិនអាចប្រើប្រាស់ប្រព័ន្ធ ឡៃហ្វាម បានទៀតឡើយ។ ទោះជាយ៉ាងណាក៏ដោយ ព័ត៌មានរបស់អ្នកនឹងមិនត្រូវបានលុបចោលភ្លាមៗនោះទេ ក្នុងករណីដែលអ្នកចង់ត្រឡប់មកប្រើប្រាស់វិញនៅពេលក្រោយ។ អ្នកអាចស្នើសុំឱ្យលុបទិន្នន័យរបស់អ្នកជាអចិន្ត្រៃយ៍ និងមិនអាចទាញយកមកវិញបាន ដោយផ្ញើការស្នើសុំទៅកាន់ litefarm.team@ubc.ca។ ប្រសិនបើអ្នកមានគម្រោងដកការយល់ព្រម ហើយចង់បានច្បាប់ចម្លងនៃទិន្នន័យរបស់អ្នក សូមធ្វើការស្នើសុំដូឆ្នោះក្នុងពេលតែមួយនៅពេលដែលអ្នកដកការយល់ព្រម។ + +**តើយើងធ្វើការផ្លាស់ប្តូរលើគោលការណ៍ឯកជនភាពដោយរបៀបណា?** + +ទោះបីជាការផ្លាស់ប្តូរភាគច្រើនអាចជាការផ្លាស់ប្តូរបន្តិចបន្តួចក៏ដោយ ឡៃហ្វាម អាចនឹងផ្លាស់ប្តូរគោលការណ៍ឯកជនភាពរបស់ខ្លួនម្តងម្កាល។ យើងនឹងបង្ហោះកំណែទម្រង់ដែលបានធ្វើបច្ចុប្បន្នភាព និងកែសម្រួលនៃគោលការណ៍ឯកជនភាពនៅលើគេហទំព័រ ឡៃហ្វាម (www.litefarm.org) ហើយនឹងជូនដំណឹងដល់អ្នកតាមរយៈកម្មវិធី នៅពេលដែលយើងធ្វើការផ្លាស់ប្តូរណាមួយ។ អ្នកនឹងតម្រូវឱ្យទទួលយកទម្រង់បែបបទយល់ព្រមថ្មី ដើម្បីបន្តប្រើប្រាស់កម្មវិធីកុំព្យូទ័រនេះ។ ប្រសិនបើអ្នកមិនទទួលយកការផ្លាស់ប្តូរទេ អ្នកនឹងអាចទាញយកទិន្នន័យរបស់អ្នកបាន ប៉ុន្តែនឹងមិនអាចបញ្ចូលទិន្នន័យថ្មីណាមួយទៅក្នុងកម្មវិធីបានឡើយ។ ការកែសម្រួលនានានឹងមានប្រសិទ្ធភាពភ្លាមៗបន្ទាប់ពីការបង្ហោះ។ ការបន្តប្រើប្រាស់គេហទំព័រនេះរបស់អ្នក បន្ទាប់ពីមានការផ្លាស់ប្តូរណាមួយនៅក្នុងគោលការណ៍ឯកជនភាពនេះ នឹងចាត់ទុកថាជាការទទួលយករបស់អ្នកចំពោះការផ្លាស់ប្តូរដូឆ្នោះ។ + +**តើយើងនឹងទាក់ទងអ្នកនៅពេលណា?** + +ប្រសិនបើអ្នកបង្កើតគណនី ឡៃហ្វាម យើងនឹងផ្ញើអ៊ីមែលម្តងម្កាលដើម្បីប្រកាសអំពីមុខងារថ្មីៗនៅក្នុង ឡៃហ្វាម, ពន្យល់អំពីការផ្លាស់ប្តូរណាមួយចំពោះកម្មវិធី, អញ្ជើញអ្នកទៅចូលរួមព្រឹត្តិការណ៍ពិសេសៗ ឬប្រាប់អ្នកអំពីគម្រោងស្រាវជ្រាវនានាដែលទិន្នន័យរបស់ ឡៃហ្វាម កំពុងជួយជំរុញឱ្យលេចចេញជារូបរាងឡើង។ យើងក៏អាចនឹងផ្ញើអ៊ីមែលទៅអ្នកម្តងម្កាលផងដែរ ដើម្បីសុំមតិកែលម្អរបស់អ្នកអំពីប្រព័ន្ធ ឬគេហទំព័រនេះ។ ការចូលរួមរបស់អ្នកនៅក្នុងការស្នើសុំបែបនេះគឺផ្អែកលើការស្ម័គ្រចិត្តទាំងស្រុង ហើយនឹងមិនប៉ះពាល់ដល់ការប្រើប្រាស់ប្រព័ន្ធរបស់អ្នកឡើយ។ + +**អាជ្ញាបណ្ណ** + +បច្ចុប្បន្ន កម្មវិធី ឡៃហ្វាម អាចប្រើប្រាស់បានដោយឥតគិតថ្លៃ។ ម្មវិធីនេះត្រូវបានផ្តល់អាជ្ញាប័ណ្ណក្រោម វី3 អាជ្ញាប័ណ្ណសាធារណៈ GNU ដែលជាអាជ្ញាប័ណ្ណសេរី និងបើកចំហកូដ​(https://www.gnu.org/licenses/quick-guide-gplv3.en.html)។ + +**សម្រាប់ព័ត៌មានបន្ថែម** + +ទាក់ទងនឹងកម្មវិធីនេះ សូមទាក់ទងមកកាន់៖ + +អ្នកគ្រប់គ្រងផលិតផល៖ litefarm.team@ubc.ca + +ទាក់ទងនឹងការសិក្សានេះ សូមទាក់ទងមកកាន់អ្នកស្រាវជ្រាវចម្បង៖ + +អ្នកស្រាវជ្រាវចម្បង៖ បណ្ឌិត ហាណា វីតមែន (hannah.wittman@ubc.ca) + +**ប្រសិនបើអ្នកមានការព្រួយបារម្ភ ឬការត្អូញត្អែរណាមួយអំពីសិទ្ធិរបស់អ្នកក្នុងនាមជាអ្នកចូលរួមការស្រាវជ្រាវ និង/ឬបទពិសោធន៍របស់អ្នកក្នុងអំឡុងពេលចូលរួមក្នុងការសិក្សានេះ** + +សូមទាក់ទងទៅកាន់ខ្សែទូរស័ព្ទទទួលបណ្តឹងតវ៉ារបស់អ្នកចូលរួមការស្រាវជ្រាវ នៃសេវាសីលធម៌ស្រាវជ្រាវរបស់សាកលវិទ្យាល័យ UBC តាមរយៈលេខទូរស័ព្ទ 604-822-8598 ឬផ្ញើអ៊ីមែលទៅកាន់ RSIL@ors.ubc.ca ក្នុងករណីនៅឆ្ងាយ ឬហៅទូរស័ព្ទដោយឥតគិតថ្លៃតាមរយៈលេខ 1-877-822-8598។ + +**ការយល់ព្រម** + +ដោយការចុចប៊ូតុង «យល់ព្រម» នៅខាងក្រោម នេះបញ្ជាក់ថាអ្នកបានទាញយកច្បាប់ចម្លងនៃទម្រង់បែបបទយល់ព្រម និងគោលការណ៍ឯកជនភាពនេះសម្រាប់ទុកជាឯកសារផ្ទាល់ខ្លួនរបស់អ្នករួចរាល់ហើយ ព្រមទាំងយល់ព្រមចូលរួមក្នុងការសិក្សានេះ។ + +លេខសម្គាល់សីលធម៌នៃការសិក្សារបស់ UBC៖ H19-01482 diff --git a/packages/webapp/src/containers/Insights/Survey/SurveyInsightTile.tsx b/packages/webapp/src/containers/Insights/Survey/SurveyInsightTile.tsx new file mode 100644 index 0000000000..0301934789 --- /dev/null +++ b/packages/webapp/src/containers/Insights/Survey/SurveyInsightTile.tsx @@ -0,0 +1,92 @@ +/* + * Copyright 2026 LiteFarm.org + * This file is part of LiteFarm. + * + * LiteFarm is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * LiteFarm is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details, see . + */ + +import { useSelector } from 'react-redux'; +import { useHistory } from 'react-router-dom'; +import { useTranslation } from 'react-i18next'; +import { BsChevronRight } from 'react-icons/bs'; +import insightStyles from '../styles.module.scss'; +import { Semibold, Text } from '../../../components/Typography'; +import { useGetLatestSurveyResponseQuery } from '../../../store/api/surveyApi'; +import { surveyInProgressSelector } from './surveyDraftSlice'; +import { useSurveyTitle } from './useSurveyTitle'; +import { surveyHasResultsPage } from './surveyConfig'; + +interface SurveyInsightTileProps { + surveyId: string; + image: string; + index: number; +} + +/** + * One survey row in the Insights list. Owns its own saved-response query so each survey can show + * its individual status (loading / in progress / completed / not filled) and link to either the + * survey or its results. + */ +function SurveyInsightTile({ surveyId, image, index }: SurveyInsightTileProps) { + const { t } = useTranslation(); + const history = useHistory(); + const title = useSurveyTitle(surveyId); + + const { + data: surveyResponse, + isError, + isFetching, + } = useGetLatestSurveyResponseQuery({ surveyKey: surveyId }); + const inProgress = useSelector(surveyInProgressSelector(surveyId)); + + const isCompleted = !isError && !!surveyResponse?.id; + + let currentData = t('INSIGHTS.TAPE.NOT_FILLED'); + if (isFetching) { + currentData = t('common:LOADING'); + } else if (inProgress) { + currentData = t('INSIGHTS.TAPE.IN_PROGRESS'); + } else if (isCompleted) { + currentData = surveyHasResultsPage(surveyId) + ? t('INSIGHTS.TAPE.COMPLETED') + : t('common:COMPLETED'); + } + + const isLoading = currentData === t('common:LOADING'); + const route = isCompleted + ? `/insights/survey/${surveyId}/results` + : `/insights/survey/${surveyId}`; + + return ( +
+
history.push(route)} + > + {title} +
+ {title} + {`${t('INSIGHTS.CURRENT')}: ${currentData ?? 0}`} +
+ +
+
+
+ ); +} + +export default SurveyInsightTile; diff --git a/packages/webapp/src/containers/Insights/TapeSurvey/TapeResults.tsx b/packages/webapp/src/containers/Insights/Survey/TapeResults.tsx similarity index 89% rename from packages/webapp/src/containers/Insights/TapeSurvey/TapeResults.tsx rename to packages/webapp/src/containers/Insights/Survey/TapeResults.tsx index dd0ee01eee..96351bb345 100644 --- a/packages/webapp/src/containers/Insights/TapeSurvey/TapeResults.tsx +++ b/packages/webapp/src/containers/Insights/Survey/TapeResults.tsx @@ -31,7 +31,7 @@ import insightStyles from '../styles.module.scss'; import { Semibold } from '../../../components/Typography'; import PageTitle from '../../../components/PageTitle'; import { roundToOne } from '../../../util/rounding'; -import { useGetTapeSurveyQuery } from '../../../store/api/tapeSurveyApi'; +import { useGetLatestSurveyResponseQuery } from '../../../store/api/surveyApi'; import { enqueueErrorSnackbar, snackbarSelector } from '../../Snackbar/snackbarSlice'; const CHART_COLOR = 'rgba(85, 143, 112, 1)'; // --Colors-Secondary-Secondary-green-700 @@ -47,20 +47,26 @@ interface TAPEDimension { maxScore: number; } -function TAPEResults() { +function TAPEResults({ surveyId = 'tape' }: { surveyId?: string }) { const { t } = useTranslation(); const history = useHistory(); const dispatch = useDispatch(); - const { data: surveyData, error: surveyDataError } = useGetTapeSurveyQuery(); + const { + data: surveyData, + error: surveyDataError, + isSuccess, + } = useGetLatestSurveyResponseQuery({ + surveyKey: surveyId, + }); const { survey_response } = surveyData || {}; const notifications: { message: string }[] = useSelector(snackbarSelector); useEffect(() => { - // Redirect back to survey page if no saved survey data is found - // (e.g. if user tries to access results page directly without completing survey) - if (surveyDataError && 'status' in surveyDataError && surveyDataError?.status === 404) { - history.replace('/Insights/tape'); + if (isSuccess && !surveyData) { + // No saved survey for this farm: send the user to fill it in (e.g. if they open the results + // page directly without completing the survey). + history.replace(`/insights/survey/${surveyId}`); } else if (surveyDataError) { const activeError = notifications.find( ({ message }) => message === t('INSIGHTS.TAPE.RESULTS_LOAD_ERROR'), @@ -69,7 +75,7 @@ function TAPEResults() { dispatch(enqueueErrorSnackbar(t('INSIGHTS.TAPE.RESULTS_LOAD_ERROR'))); } } - }, [surveyDataError]); + }, [surveyDataError, isSuccess, surveyData]); const tapeData = survey_response ? analyzeTAPEData(survey_response) : []; diff --git a/packages/webapp/src/containers/Insights/Survey/ThankYouResults.tsx b/packages/webapp/src/containers/Insights/Survey/ThankYouResults.tsx new file mode 100644 index 0000000000..5448dcca1a --- /dev/null +++ b/packages/webapp/src/containers/Insights/Survey/ThankYouResults.tsx @@ -0,0 +1,43 @@ +/* + * Copyright 2026 LiteFarm.org + * This file is part of LiteFarm. + * + * LiteFarm is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * LiteFarm is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details, see . + */ + +import { useTranslation } from 'react-i18next'; +import styles from './styles.module.scss'; +import insightStyles from '../styles.module.scss'; +import { Semibold } from '../../../components/Typography'; +import PageTitle from '../../../components/PageTitle'; +import { useSurveyTitle } from './useSurveyTitle'; + +/** + * Default results component for surveys that do not need a custom visualization. Rendered by the + * survey results route whenever a survey's entry in SURVEY_INFO does not name its own component. + */ +function ThankYouResults({ surveyId }: { surveyId: string }) { + const { t } = useTranslation(); + const surveyTitle = useSurveyTitle(surveyId); + + return ( +
+ +
+
+ {t('INSIGHTS.SURVEY.THANK_YOU')} +
+
+
+ ); +} + +export default ThankYouResults; diff --git a/packages/webapp/src/containers/Insights/TapeSurvey/index.tsx b/packages/webapp/src/containers/Insights/Survey/index.tsx similarity index 53% rename from packages/webapp/src/containers/Insights/TapeSurvey/index.tsx rename to packages/webapp/src/containers/Insights/Survey/index.tsx index 39c9b6b55f..9f7dd3428e 100644 --- a/packages/webapp/src/containers/Insights/TapeSurvey/index.tsx +++ b/packages/webapp/src/containers/Insights/Survey/index.tsx @@ -15,73 +15,98 @@ import { useCallback, useEffect } from 'react'; import { useDispatch, useSelector } from 'react-redux'; -import { useHistory } from 'react-router-dom'; +import { useHistory, useParams } from 'react-router-dom'; import { CompleteEvent } from 'survey-core'; import clsx from 'clsx'; import { useTranslation } from 'react-i18next'; -import { useTapeSurveyPrepopulatedData } from './useTapeSurveyPrepopulatedData'; -import { saveSurveyProgress, clearSurvey, tapeSurveySelector } from './tapeSurveySlice'; +import { useSurveyPrepopulatedData } from './useSurveyPrepopulatedData'; +import { useSurveyTitle } from './useSurveyTitle'; +import { saveSurveyProgress, clearSurvey, surveyDraftSelector } from './surveyDraftSlice'; +import { SURVEY_INFO, getSurveyVersion } from './surveyConfig'; import { userFarmSelector } from '../../../containers/userFarmSlice'; import SurveyComponent from '../../../components/SurveyComponent'; import PageTitle from '../../../components/PageTitle'; import { usePrefetch, - useGetTapeSurveyJsonQuery, - useAddTapeSurveyMutation, -} from '../../../store/api/tapeSurveyApi'; + useGetSurveyJsonQuery, + useAddSurveyResponseMutation, +} from '../../../store/api/surveyApi'; import { enqueueErrorSnackbar, snackbarSelector } from '../../Snackbar/snackbarSlice'; import styles from './styles.module.scss'; import insightStyles from '../styles.module.scss'; -interface TAPESurveyProps { +interface SurveyProps { isCompactSideMenu: boolean; - surveyVersion: string; } -function TAPESurvey({ isCompactSideMenu, surveyVersion }: TAPESurveyProps) { +function Survey({ isCompactSideMenu }: SurveyProps) { const { t } = useTranslation(); const history = useHistory(); const dispatch = useDispatch(); + const { surveyId } = useParams<{ surveyId: string }>(); + const surveyTitle = useSurveyTitle(surveyId); // @ts-expect-error - userFarmSelector is not typed with TypeScript yet - const { farm_id } = useSelector(userFarmSelector); + const { farm_id, country_code } = useSelector(userFarmSelector); + + const surveyVersion = getSurveyVersion(surveyId, country_code); + const cdnDirectory = SURVEY_INFO[surveyId]?.cdnDirectory; const { prepopulatedData, isLoading: isPrepopulatedDataLoading } = - useTapeSurveyPrepopulatedData(); + useSurveyPrepopulatedData(surveyId); const { data: surveyJson, isLoading: isSurveyJsonLoading, isError: isSurveyJsonError, - } = useGetTapeSurveyJsonQuery(surveyVersion); + } = useGetSurveyJsonQuery( + { cdnDirectory: cdnDirectory ?? '', version: surveyVersion ?? '' }, + { skip: !cdnDirectory || !surveyVersion }, + ); - const [addTapeSurvey] = useAddTapeSurveyMutation(); - const prefetchSurveyData = usePrefetch('getTapeSurvey'); + const [addSurveyResponse] = useAddSurveyResponseMutation(); + const prefetchLatestResponse = usePrefetch('getLatestSurveyResponse'); - const { surveyDataInProgress, currentPageNo: savedPageNo } = useSelector(tapeSurveySelector); + const { surveyData: surveyDataInProgress, currentPageNo: savedPageNo } = useSelector( + surveyDraftSelector(surveyId), + ); const notifications: { message: string }[] = useSelector(snackbarSelector); const initialData = { ...prepopulatedData, ...surveyDataInProgress }; - const handleDataChange = useCallback((currentPageNo: number, surveyData: Record) => { - dispatch(saveSurveyProgress({ currentPageNo, surveyData })); - }, []); + const handleDataChange = useCallback( + (currentPageNo: number, surveyData: Record) => { + dispatch(saveSurveyProgress({ surveyId, currentPageNo, surveyData })); + }, + [dispatch, surveyId], + ); const handleComplete = useCallback( async (surveyData: any, options: CompleteEvent) => { try { - await addTapeSurvey({ survey_response: surveyData, farm_id }).unwrap(); - prefetchSurveyData(); - dispatch(clearSurvey()); - history.push('/insights/tape/results'); + await addSurveyResponse({ + survey_key: surveyId, + survey_response: surveyData, + farm_id, + }).unwrap(); + prefetchLatestResponse({ surveyKey: surveyId }); + dispatch(clearSurvey({ surveyId })); + // Replace instead of push so the submitted survey is not left in the history stack + history.replace(`/insights/survey/${surveyId}/results`); } catch { // Display the default "An error occurred and we could not save the results." message. - // (pass translated string for multiple language support) options.showSaveError(); } }, - [addTapeSurvey, dispatch, history, t], + [addSurveyResponse, prefetchLatestResponse, dispatch, history, surveyId, farm_id], ); + // Redirect to Insights if this survey is unknown or not available to the farm's country + useEffect(() => { + if (!surveyVersion) { + history.replace('/Insights'); + } + }, [surveyVersion, history]); + useEffect(() => { if (isSurveyJsonError) { const activeError = notifications.find( @@ -97,11 +122,9 @@ function TAPESurvey({ isCompactSideMenu, surveyVersion }: TAPESurveyProps) { return (
- -
- {/* wait for prepopulated data to load */} + +
+ {/* wait for prepopulated data and survey JSON to load */} {!isLoading && surveyJson && ( . + */ + +import { ComponentType } from 'react'; +import tape_survey from '../../../assets/images/insights/tape_survey.svg'; +import TapeResults from './TapeResults'; +import ThankYouResults from './ThankYouResults'; + +interface SurveyInfo { + image: string; + ResultsComponent?: ComponentType<{ surveyId: string }>; + // CDN directory under DO_CDN_URL holding the survey's `.json` definitions. + cdnDirectory: string; + // Uppercase ISO-2 country code -> CDN version to load. The 'default' key is the global fallback; + // a survey with no 'default' is available only in the countries it lists explicitly. + versionsByCountry: Record; +} + +/** + * The catalog of surveys, keyed by survey `key` (the same string stored in survey_response.survey_key). + * This is the single source of truth for the frontend: which surveys exist, the tile image and + * results component, the CDN directory, and the per-country version/availability. The database holds + * only the responses. + * + * Adding a survey: + * 1. Add a SURVEY_INFO entry here: image, ResultsComponent (omit for the generic thank-you page), + * cdnDirectory, versionsByCountry. + * 2. Add the title in useSurveyTitle.ts as a literal call: surveyKey: t('INSIGHTS..TITLE'). + * 3. Add that title string to public/locales/en/translation.json (English only; Crowdin propagates). + * 4. Upload the survey's .json to its CDN directory. + */ +export const SURVEY_INFO: Record = { + tape: { + image: tape_survey, + ResultsComponent: TapeResults, + cdnDirectory: 'tape_surveys', + versionsByCountry: { default: 'fao', AU: 'au' }, + }, + cathi_gao: { + image: tape_survey, + cdnDirectory: 'idems_surveys', + versionsByCountry: { NE: 'cathi_gao' }, // Niger only research project + }, +}; + +/** + * The CDN version of a survey for a given country, or undefined when the survey does not exist or is + * not available in that country. A country-specific entry wins over the global 'default'. + */ +export const getSurveyVersion = (surveyId: string, countryCode?: string): string | undefined => { + const info = SURVEY_INFO[surveyId]; + if (!info) { + return undefined; + } + return (countryCode && info.versionsByCountry[countryCode]) ?? info.versionsByCountry.default; +}; + +/** + * The survey ids available to a farm in the given country: those with a country-specific or global + * version. Drives the Insights tile list. + */ +export const getAvailableSurveyIds = (countryCode?: string): string[] => + Object.keys(SURVEY_INFO).filter( + (surveyId) => getSurveyVersion(surveyId, countryCode) !== undefined, + ); + +/** + * The results component for a survey, defaulting to the generic thank-you page when the survey + * defines none. + */ +export const getResultsComponent = (surveyId: string): ComponentType<{ surveyId: string }> => + SURVEY_INFO[surveyId]?.ResultsComponent ?? ThankYouResults; + +/** + * Whether a survey shows its own results page rather than the generic thank-you confirmation. + * Drives the completed-status wording on the Insights tile. + */ +export const surveyHasResultsPage = (surveyId: string): boolean => + getResultsComponent(surveyId) !== ThankYouResults; diff --git a/packages/webapp/src/containers/Insights/Survey/surveyDraftSlice.ts b/packages/webapp/src/containers/Insights/Survey/surveyDraftSlice.ts new file mode 100644 index 0000000000..47327dacfd --- /dev/null +++ b/packages/webapp/src/containers/Insights/Survey/surveyDraftSlice.ts @@ -0,0 +1,76 @@ +/* + * Copyright 2026 LiteFarm.org + * This file is part of LiteFarm. + * + * LiteFarm is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * LiteFarm is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details, see . + */ + +import { createSlice, PayloadAction } from '@reduxjs/toolkit'; +import { createSelector } from 'reselect'; + +interface SurveyDraft { + currentPageNo: number; + surveyData: Record; +} + +interface SurveyDraftState { + bySurveyId: Record; +} + +const initialState: SurveyDraftState = { + bySurveyId: {}, +}; + +const emptyDraft: SurveyDraft = { currentPageNo: 0, surveyData: {} }; + +const surveyDraftSlice = createSlice({ + name: 'surveyDraftReducer', + initialState, + reducers: { + saveSurveyProgress: ( + state, + action: PayloadAction<{ + surveyId: string; + currentPageNo: number; + surveyData: Record; + }>, + ) => { + const { surveyId, currentPageNo, surveyData } = action.payload; + const previous = state.bySurveyId[surveyId]?.surveyData ?? {}; + state.bySurveyId[surveyId] = { + currentPageNo, + surveyData: { ...previous, ...surveyData }, + }; + }, + clearSurvey: (state, action: PayloadAction<{ surveyId: string }>) => { + delete state.bySurveyId[action.payload.surveyId]; + }, + }, +}); + +export const { saveSurveyProgress, clearSurvey } = surveyDraftSlice.actions; +export default surveyDraftSlice.reducer; + +// Selectors +const surveyDraftStateSelector = (state: any): SurveyDraftState => + state.farmStateReducer[surveyDraftSlice.name] || initialState; + +export const surveyDraftSelector = (surveyId: string) => + createSelector( + [surveyDraftStateSelector], + (draftState) => draftState.bySurveyId[surveyId] || emptyDraft, + ); + +export const surveyInProgressSelector = (surveyId: string) => + createSelector( + [surveyDraftStateSelector], + (draftState) => Object.keys(draftState.bySurveyId[surveyId]?.surveyData ?? {}).length > 0, + ); diff --git a/packages/webapp/src/containers/Insights/TapeSurvey/useTapeSurveyPrepopulatedData.ts b/packages/webapp/src/containers/Insights/Survey/useSurveyPrepopulatedData.ts similarity index 80% rename from packages/webapp/src/containers/Insights/TapeSurvey/useTapeSurveyPrepopulatedData.ts rename to packages/webapp/src/containers/Insights/Survey/useSurveyPrepopulatedData.ts index aae3e796b8..604dd01663 100644 --- a/packages/webapp/src/containers/Insights/TapeSurvey/useTapeSurveyPrepopulatedData.ts +++ b/packages/webapp/src/containers/Insights/Survey/useSurveyPrepopulatedData.ts @@ -20,18 +20,20 @@ import { parseGoogleGeocodedAddress } from '../../../util/google-maps/parseAddre import { userFarmSelector } from '../../userFarmSlice'; import { UserFarm } from '../../../types'; -interface TapeSurveyPrepopulatedData { +interface SurveyPrepopulatedData { location_province?: string; location_municipality?: string; country?: string; gps_lat?: number; gps_lon?: number; - // Other pre-populated fields as needed: - // - Do you raise animals - // - Number of unique species in crop management plans } -export const useTapeSurveyPrepopulatedData = () => { +/** + * Returns pre-populated answers for a survey. Only the TAPE survey geocodes the farm address to + * pre-fill location/GPS fields; other surveys start empty. Survey-specific pre-population is added + * here per survey id. + */ +export const useSurveyPrepopulatedData = (surveyId: string) => { const { isLoaded } = useGoogleMapsLoader(['geocoding']); // @ts-expect-error -- userFarmSelector issue @@ -41,6 +43,11 @@ export const useTapeSurveyPrepopulatedData = () => { const [isLoading, setIsLoading] = useState(true); useEffect(() => { + if (surveyId !== 'tape') { + setIsLoading(false); + return; + } + const fetchGeocodedData = async () => { if (!isLoaded) { return; @@ -54,7 +61,7 @@ export const useTapeSurveyPrepopulatedData = () => { try { const parsedAddress = await parseGoogleGeocodedAddress(userFarm.address); - const data: TapeSurveyPrepopulatedData = { + const data: SurveyPrepopulatedData = { country: parsedAddress.country, location_province: parsedAddress.location_province, location_municipality: parsedAddress.location_municipality, @@ -71,7 +78,7 @@ export const useTapeSurveyPrepopulatedData = () => { }; fetchGeocodedData(); - }, [isLoaded, userFarm?.address, userFarm?.grid_points]); + }, [surveyId, isLoaded, userFarm?.address, userFarm?.grid_points]); return { prepopulatedData, isLoading }; }; diff --git a/packages/webapp/src/containers/Insights/Survey/useSurveyTitle.ts b/packages/webapp/src/containers/Insights/Survey/useSurveyTitle.ts new file mode 100644 index 0000000000..a65edd3164 --- /dev/null +++ b/packages/webapp/src/containers/Insights/Survey/useSurveyTitle.ts @@ -0,0 +1,33 @@ +/* + * Copyright 2026 LiteFarm.org + * This file is part of LiteFarm. + * + * LiteFarm is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * LiteFarm is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details, see . + */ + +import { useTranslation } from 'react-i18next'; + +/** + * Resolves a survey's display title. Each title is a literal t() call so i18next-parser extracts + * the key; add a literal entry per survey. Surveys without an entry fall back to a generic title. + * Kept free of component imports so it can be used by both the tile list and the survey/results + * pages without an import cycle. + */ +export const useSurveyTitle = (surveyId: string): string => { + const { t } = useTranslation(); + + const titleBySurveyId: Record = { + tape: t('INSIGHTS.TAPE.TITLE'), + cathi_gao: t('INSIGHTS.CATHI_GAO.TITLE'), + }; + + return titleBySurveyId[surveyId] ?? t('INSIGHTS.SURVEY.TITLE'); +}; diff --git a/packages/webapp/src/containers/Insights/TapeSurvey/getSurveyVersion.ts b/packages/webapp/src/containers/Insights/TapeSurvey/getSurveyVersion.ts deleted file mode 100644 index 61a562d487..0000000000 --- a/packages/webapp/src/containers/Insights/TapeSurvey/getSurveyVersion.ts +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright 2026 LiteFarm.org - * This file is part of LiteFarm. - * - * LiteFarm is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * LiteFarm is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details, see . - */ - -const COUNTRY_VERSIONS = ['AU']; - -/** - * Returns the survey version key used to fetch the correct JSON from DO CDN, - * based on the farm's 2-letter ISO country code. - * - * To add a new country-specific version: - * 1. Upload `tape_surveys/.json` to the DO Spaces bucket. - * 2. Add a country_code to `COUNTRY_VERSIONS`. - */ -export const getSurveyVersion = (countryCode: string | undefined): string | undefined => { - return countryCode && COUNTRY_VERSIONS.includes(countryCode) ? countryCode.toLowerCase() : 'fao'; -}; diff --git a/packages/webapp/src/containers/Insights/TapeSurvey/tapeSurveySlice.ts b/packages/webapp/src/containers/Insights/TapeSurvey/tapeSurveySlice.ts deleted file mode 100644 index fe25fcd123..0000000000 --- a/packages/webapp/src/containers/Insights/TapeSurvey/tapeSurveySlice.ts +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright 2026 LiteFarm.org - * This file is part of LiteFarm. - * - * LiteFarm is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * LiteFarm is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details, see . - */ - -import { createSlice, PayloadAction } from '@reduxjs/toolkit'; -import { createSelector } from 'reselect'; - -interface TapeSurveyState { - currentPageNo: number; - surveyDataInProgress: Record; -} - -const initialState: TapeSurveyState = { - currentPageNo: 0, - surveyDataInProgress: {}, -}; - -const tapeSurveySlice = createSlice({ - name: 'tapeSurveyReducer', - initialState, - reducers: { - saveSurveyProgress: ( - state, - action: PayloadAction<{ - currentPageNo: number; - surveyData: Record; - }>, - ) => { - state.currentPageNo = action.payload.currentPageNo; - state.surveyDataInProgress = { ...state.surveyDataInProgress, ...action.payload.surveyData }; - }, - reopenSurvey: (state) => { - state.currentPageNo = 0; - }, - clearSurvey: () => initialState, - }, -}); - -export const { saveSurveyProgress, reopenSurvey, clearSurvey } = tapeSurveySlice.actions; -export default tapeSurveySlice.reducer; - -// Selectors -export const tapeSurveySelector = (state: any) => - // Re-evaluate placement in farmStateReducer when adding backend - state.farmStateReducer[tapeSurveySlice.name] || initialState; - -export const tapeSurveyStatusSelector = createSelector([tapeSurveySelector], (tapeSurvey) => ({ - inProgress: Object.keys(tapeSurvey.surveyDataInProgress).length > 0, -})); diff --git a/packages/webapp/src/containers/Insights/index.jsx b/packages/webapp/src/containers/Insights/index.jsx index f131aa5f03..efd42fd5ad 100644 --- a/packages/webapp/src/containers/Insights/index.jsx +++ b/packages/webapp/src/containers/Insights/index.jsx @@ -19,7 +19,6 @@ import { useDispatch, useSelector } from 'react-redux'; import { useTranslation } from 'react-i18next'; import styles from './styles.module.scss'; // images -import tape_survey from '../../assets/images/insights/tape_survey.svg'; import soil_om from '../../assets/images/insights/soil_om.svg'; import labour_happiness from '../../assets/images/insights/labour_happiness.svg'; import biodiversity from '../../assets/images/insights/biodiversity.svg'; @@ -34,20 +33,18 @@ import { pricesSelector, soilOMSelector, } from './selectors'; -import { tapeSurveyStatusSelector } from './TapeSurvey/tapeSurveySlice'; import InfoBoxComponent from '../../components/InfoBoxComponent'; import { BsChevronRight } from 'react-icons/bs'; import { isAdminSelector, userFarmSelector } from '../userFarmSlice'; import { Semibold, Text, Title } from '../../components/Typography'; import { useIsOffline } from '../hooks/useOfflineDetector/useIsOffline'; -import { useGetTapeSurveyQuery } from '../../store/api/tapeSurveyApi'; -import { getSurveyVersion } from './TapeSurvey/getSurveyVersion'; +import { SURVEY_INFO, getAvailableSurveyIds } from './Survey/surveyConfig'; +import SurveyInsightTile from './Survey/SurveyInsightTile'; const Insights = () => { const history = useHistory(); const farm = useSelector(userFarmSelector); - const tapeStatus = useSelector(tapeSurveyStatusSelector); const pricesDistance = useSelector(pricesDistanceSelector); const soilOMData = useSelector(soilOMSelector); const labourHappinessData = useSelector(labourHappinessSelector); @@ -59,22 +56,7 @@ const Insights = () => { const dispatch = useDispatch(); const { t } = useTranslation(); - const surveyVersion = getSurveyVersion(farm?.country_code); - const { - data: tapeSurvey, - isError: isTapeSurveyError, - isFetching: isTapeSurveyFetching, - } = useGetTapeSurveyQuery(); - - const isTapeSurveyCompleted = !isTapeSurveyError && !!tapeSurvey?.id; - const items = [ - { - label: t('INSIGHTS.TAPE.TITLE'), - image: tape_survey, - route: isTapeSurveyCompleted ? 'tape/results' : 'tape', - data_point: 'TAPE', - }, { label: t('INSIGHTS.SOIL_OM.TITLE'), image: soil_om, @@ -143,17 +125,7 @@ const Insights = () => { }; const insightData = useMemo(() => { - let tapeCurrentData = t('INSIGHTS.TAPE.NOT_FILLED'); - if (isTapeSurveyFetching) { - tapeCurrentData = t('common:LOADING'); - } else if (tapeStatus.inProgress) { - tapeCurrentData = t('INSIGHTS.TAPE.IN_PROGRESS'); - } else if (isTapeSurveyCompleted) { - tapeCurrentData = t('INSIGHTS.TAPE.COMPLETED'); - } - const insightData = {}; - insightData['TAPE'] = tapeCurrentData; insightData['SoilOM'] = (soilOMData.preview ?? '0') + '%'; insightData['LabourHappiness'] = labourHappinessData.preview ? labourHappinessData.preview + '/5' @@ -163,28 +135,30 @@ const Insights = () => { ? t('INSIGHTS.PRICES.PERCENT_OF_MARKET', { percentage: pricesData.preview }) : t('INSIGHTS.UNAVAILABLE'); return insightData; - }, [ - tapeStatus?.inProgress, - isTapeSurveyFetching, - isTapeSurveyCompleted, - soilOMData, - labourHappinessData, - biodiversityData, - pricesData, - ]); + }, [soilOMData, labourHappinessData, biodiversityData, pricesData]); + + // Surveys are shown only to admins and only when online. getAvailableSurveyIds gates the list to + // surveys available in the farm's country (see SURVEY_INFO). + const surveyTiles = useMemo(() => { + if (isOffline || !isAdmin) { + return []; + } + return getAvailableSurveyIds(farm?.country_code).map((surveyId, index) => ( + + )); + }, [farm?.country_code, isOffline, isAdmin]); const renderedItems = useMemo(() => { - return ( - insightData && - items - .filter( - (item) => !((isOffline || !isAdmin || !surveyVersion) && item.data_point === 'TAPE'), - ) - .map((item, index) => { - return renderItem(item, index, insightData[item.data_point]); - }) + const otherTiles = items.map((item, index) => + renderItem(item, surveyTiles.length + index, insightData[item.data_point]), ); - }, [insightData, isOffline]); + return [...surveyTiles, ...otherTiles]; + }, [insightData, isOffline, surveyTiles]); return (
diff --git a/packages/webapp/src/containers/saga.js b/packages/webapp/src/containers/saga.js index 05b20e55cb..b6d7e24d0b 100644 --- a/packages/webapp/src/containers/saga.js +++ b/packages/webapp/src/containers/saga.js @@ -101,6 +101,7 @@ import { userFarmsByFarmSelector, } from './userFarmSlice'; import { logUserInfoSuccess, userLogReducerSelector } from './userLogSlice'; +import { resetFarmStateReducer } from '../store/actionTypes'; import { api, invalidateTags } from '../store/api/apiSlice'; import { locationApi } from '../store/api/locationApi'; import { FarmLibraryTags, FarmTags } from '../store/api/apiTags'; @@ -555,6 +556,7 @@ export function* fetchAllSaga() { } export function* clearOldFarmStateSaga() { + yield put(resetFarmStateReducer()); yield put(resetTasks()); yield put(resetDateRange()); releaseFarmScopedQuerySubscriptions(); diff --git a/packages/webapp/src/locales/km/rcYearCalendar.json b/packages/webapp/src/locales/km/rcYearCalendar.json new file mode 100644 index 0000000000..d72a5da75a --- /dev/null +++ b/packages/webapp/src/locales/km/rcYearCalendar.json @@ -0,0 +1,59 @@ +{ + "days": [ + "ថ្ងៃអាទិត្យ", + "ថ្ងៃច័ន្ទ", + "ថ្ងៃអង្គារ", + "ថ្ងៃពុធ", + "ថ្ងៃព្រហស្បតិ៍", + "ថ្ងៃសុក្រ", + "ថ្ងៃសោរ៍" + ], + "daysShort": [ + "អាទិត្យ", + "ច័ន្ទ", + "អង្គារ", + "ពុធ", + "ព្រហស្បតិ៍", + "សុក្រ", + "សៅរ៍" + ], + "daysMin": [ + "អា", + "ច", + "អ", + "ពុ", + "ព្រ", + "សុ", + "ស" + ], + "months": [ + "ខែមករា", + "ខែកុម្ភៈ", + "ខែមីនា", + "ខែមេសា", + "ខែឧសភា", + "ខែមិថុនា", + "ខែកក្កដា", + "ខែសីហា", + "ខែកញ្ញា", + "ខែតុលា", + "ខែវិច្ឆិកា", + "ខែធ្នូ" + ], + "monthsShort": [ + "មករា", + "កុម្ភៈ", + "មីនា", + "មេសា", + "ឧសភា", + "មិថុនា", + "កក្កដា", + "សីហា", + "កញ្ញា", + "តុលា", + "វិច្ឆិកា", + "ធ្នូ" + ], + "weekShort": "សប្តាហ៍", + "weekStart": "០" +} diff --git a/packages/webapp/src/locales/km/rrule.json b/packages/webapp/src/locales/km/rrule.json new file mode 100644 index 0000000000..75131c3e2c --- /dev/null +++ b/packages/webapp/src/locales/km/rrule.json @@ -0,0 +1,56 @@ +{ + "getText": { + "every": "រៀងរាល់", + "until": "រហូតដល់", + "day": "ថ្ងៃ", + "days": "ថ្ងៃ", + "week": "សប្តាហ៍", + "weeks": "សប្តាហ៍", + "on": "លើ", + "in": "ក្នុង", + "on the": "នៅលើ", + "for": "សម្រាប់", + "and": "និង", + "or": "ឬ", + "at": "នៅ", + "last": "ចុងក្រោយ", + "st": "ទីមួយ", + "nd": "ទីពីរ", + "rd": "ទីបី", + "th": "ទី", + "(~ approximate)": "(~ ប្រហាក់ប្រហែល)", + "times": "ចំនួនដង", + "time": "ពេល", + "minutes": "នាទី", + "hours": "ម៉ោង", + "weekdays": "ថ្ងៃធ្វើការ", + "weekday": "ថ្ងៃធ្វើការ", + "months": "ខែ", + "month": "ខែ", + "years": "ឆ្នាំ", + "year": "ឆ្នាំ" + }, + "dayNames": [ + "ថ្ងៃអាទិត្យ", + "ថ្ងៃច័ន្ទ", + "ថ្ងៃអង្គារ", + "ថ្ងៃពុធ", + "ថ្ងៃព្រហស្បតិ៍", + "ថ្ងៃសុក្រ", + "ថ្ងៃសៅរ៍" + ], + "monthNames": [ + "ខែមករា", + "ខែកុម្ភៈ", + "ខែមីនា", + "ខែមេសា", + "ខែឧសភា", + "ខែមិថុនា", + "ខែកក្កដា", + "ខែសីហា", + "ខែកញ្ញា", + "ខែតុលា", + "ខែវិច្ឆិកា", + "ខែធ្នូ" + ] +} diff --git a/packages/webapp/src/main.jsx b/packages/webapp/src/main.jsx index c575486a3c..14b77a0715 100644 --- a/packages/webapp/src/main.jsx +++ b/packages/webapp/src/main.jsx @@ -70,7 +70,7 @@ if (import.meta.env.VITE_SENTRY_DSN) { Sentry.init({ dsn: import.meta.env.VITE_SENTRY_DSN, integrations: [new Integrations.BrowserTracing()], - release: '3.12.0', + release: '3.12.1', // Set tracesSampleRate to 1.0 to capture 100% // of transactions for performance monitoring. // We recommend adjusting this value in production diff --git a/packages/webapp/src/routes/SurveyRoutes.tsx b/packages/webapp/src/routes/SurveyRoutes.tsx new file mode 100644 index 0000000000..c1bec1d65f --- /dev/null +++ b/packages/webapp/src/routes/SurveyRoutes.tsx @@ -0,0 +1,41 @@ +/* + * Copyright 2026 LiteFarm.org + * This file is part of LiteFarm. + * + * LiteFarm is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * LiteFarm is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details, see . + */ + +import { Redirect, Switch, Route, useParams } from 'react-router-dom'; +import Survey from '../containers/Insights/Survey'; +import { getResultsComponent } from '../containers/Insights/Survey/surveyConfig'; + +// Renders the results component the survey declares (or the generic thank-you page). +const SurveyResults = () => { + const { surveyId } = useParams<{ surveyId: string }>(); + const ResultsComponent = getResultsComponent(surveyId); + return ; +}; + +const SurveyRoutes = ({ isCompactSideMenu }: { isCompactSideMenu: boolean }) => { + return ( + + + + + + + + } /> + + ); +}; + +export default SurveyRoutes; diff --git a/packages/webapp/src/routes/TapeRoutes.tsx b/packages/webapp/src/routes/TapeRoutes.tsx deleted file mode 100644 index 6f84628d32..0000000000 --- a/packages/webapp/src/routes/TapeRoutes.tsx +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright 2026 LiteFarm.org - * This file is part of LiteFarm. - * - * LiteFarm is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * LiteFarm is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details, see . - */ - -import React from 'react'; -import { Redirect, Switch, Route } from 'react-router-dom'; -import { useSelector } from 'react-redux'; -import { getSurveyVersion } from '../containers/Insights/TapeSurvey/getSurveyVersion'; -import { userFarmSelector } from '../containers/userFarmSlice'; - -const TapeSurvey = React.lazy(() => import('../containers/Insights/TapeSurvey')); -const TapeResults = React.lazy(() => import('../containers/Insights/TapeSurvey/TapeResults')); - -const TapeRoutes = ({ isCompactSideMenu }: { isCompactSideMenu: boolean }) => { - // @ts-expect-error -- userFarmSelector issue - const { country_code } = useSelector(userFarmSelector); - const surveyVersion = getSurveyVersion(country_code); - - if (!surveyVersion) { - return ; - } - - return ( - - - - - - - - } /> - - ); -}; - -export default TapeRoutes; diff --git a/packages/webapp/src/routes/index.jsx b/packages/webapp/src/routes/index.jsx index 43aeafe67d..37ed5405b5 100644 --- a/packages/webapp/src/routes/index.jsx +++ b/packages/webapp/src/routes/index.jsx @@ -60,7 +60,7 @@ const SoilOM = React.lazy(() => import('../containers/Insights/SoilOM')); const LabourHappiness = React.lazy(() => import('../containers/Insights/LabourHappiness')); const Biodiversity = React.lazy(() => import('../containers/Insights/Biodiversity')); const Prices = React.lazy(() => import('../containers/Insights/Prices')); -const TapeRoutes = React.lazy(() => import('./TapeRoutes')); +const SurveyRoutes = React.lazy(() => import('./SurveyRoutes')); const ExpiredTokenScreen = React.lazy(() => import('../containers/ExpiredTokenScreen')); const Map = React.lazy(() => import('../containers/Map')); @@ -69,8 +69,8 @@ const LocationDetailsRoutes = React.lazy(() => import('./LocationDetailsRoutes') // Import config separately to access allLocationTypes at render time import { allLocationTypes } from './locationRouteConfig'; -const PostLocationDetailForm = React.lazy(() => - import('../containers/LocationDetails/PostLocationDetailForm'), +const PostLocationDetailForm = React.lazy( + () => import('../containers/LocationDetails/PostLocationDetailForm'), ); const CropManagement = React.lazy(() => import('../containers/Crop/CropManagement')); @@ -84,34 +84,34 @@ const AddCropVariety = React.lazy(() => import('../containers/AddCropVariety/Add const EditCropVariety = React.lazy(() => import('../containers/EditCropVariety')); const ComplianceInfo = React.lazy(() => import('../containers/AddCropVariety/ComplianceInfo')); const AddNewCrop = React.lazy(() => import('../containers/AddNewCrop')); -const PlantingLocation = React.lazy(() => - import('../containers/Crop/AddManagementPlan/PlantingLocation'), +const PlantingLocation = React.lazy( + () => import('../containers/Crop/AddManagementPlan/PlantingLocation'), ); const Transplant = React.lazy(() => import('../containers/Crop/AddManagementPlan/Transplant')); const PlantingDate = React.lazy(() => import('../containers/Crop/AddManagementPlan/PlantingDate')); -const PlantingMethod = React.lazy(() => - import('../containers/Crop/AddManagementPlan/PlantingMethod'), +const PlantingMethod = React.lazy( + () => import('../containers/Crop/AddManagementPlan/PlantingMethod'), ); -const PlantInContainer = React.lazy(() => - import('../containers/Crop/AddManagementPlan/PlantInContainer'), +const PlantInContainer = React.lazy( + () => import('../containers/Crop/AddManagementPlan/PlantInContainer'), ); -const PlantBroadcast = React.lazy(() => - import('../containers/Crop/AddManagementPlan/BroadcastPlan'), +const PlantBroadcast = React.lazy( + () => import('../containers/Crop/AddManagementPlan/BroadcastPlan'), ); const BedPlan = React.lazy(() => import('../containers/Crop/AddManagementPlan/BedPlan/BedPlan')); -const BedPlanGuidance = React.lazy(() => - import('../containers/Crop/AddManagementPlan/BedPlan/BedPlanGuidance'), +const BedPlanGuidance = React.lazy( + () => import('../containers/Crop/AddManagementPlan/BedPlan/BedPlanGuidance'), ); -const ManagementPlanName = React.lazy(() => - import('../containers/Crop/AddManagementPlan/ManagementPlanName'), +const ManagementPlanName = React.lazy( + () => import('../containers/Crop/AddManagementPlan/ManagementPlanName'), ); const RowMethod = React.lazy(() => import('../containers/Crop/AddManagementPlan/RowMethod')); -const RowMethodGuidance = React.lazy(() => - import('../containers/Crop/AddManagementPlan/RowMethod/RowGuidance'), +const RowMethodGuidance = React.lazy( + () => import('../containers/Crop/AddManagementPlan/RowMethod/RowGuidance'), ); -const PlantedAlready = React.lazy(() => - import('../containers/Crop/AddManagementPlan/PlantedAlready'), +const PlantedAlready = React.lazy( + () => import('../containers/Crop/AddManagementPlan/PlantedAlready'), ); const Documents = React.lazy(() => import('../containers/Documents')); @@ -120,60 +120,63 @@ const EditDocument = React.lazy(() => import('../containers/Documents/Edit')); const AddDocument = React.lazy(() => import('../containers/Documents/Add')); const MainDocument = React.lazy(() => import('../containers/Documents/Main')); -const CertificationReportingPeriod = React.lazy(() => - import('../containers/Certifications/ReportingPeriod'), +const CertificationReportingPeriod = React.lazy( + () => import('../containers/Certifications/ReportingPeriod'), ); const CertificationSurvey = React.lazy(() => import('../containers/Certifications/Survey')); -const InterestedOrganic = React.lazy(() => - import('../containers/OrganicCertifierSurvey/InterestedOrganic/UpdateInterestedOrganic'), +const InterestedOrganic = React.lazy( + () => import('../containers/OrganicCertifierSurvey/InterestedOrganic/UpdateInterestedOrganic'), ); -const CertificationSelection = React.lazy(() => - import( - '../containers/OrganicCertifierSurvey/CertificationSelection/UpdateCertificationSelection' - ), +const CertificationSelection = React.lazy( + () => + import( + '../containers/OrganicCertifierSurvey/CertificationSelection/UpdateCertificationSelection' + ), ); -const CertifierSelectionMenu = React.lazy(() => - import( - '../containers/OrganicCertifierSurvey/CertifierSelectionMenu/UpdateCertifierSelectionMenu' - ), +const CertifierSelectionMenu = React.lazy( + () => + import( + '../containers/OrganicCertifierSurvey/CertifierSelectionMenu/UpdateCertifierSelectionMenu' + ), ); -const SetCertificationSummary = React.lazy(() => - import( - '../containers/OrganicCertifierSurvey/SetCertificationSummary/UpdateSetCertificationSummary' - ), +const SetCertificationSummary = React.lazy( + () => + import( + '../containers/OrganicCertifierSurvey/SetCertificationSummary/UpdateSetCertificationSummary' + ), ); -const RequestCertifier = React.lazy(() => - import('../containers/OrganicCertifierSurvey/RequestCertifier/UpdateRequestCertifier'), +const RequestCertifier = React.lazy( + () => import('../containers/OrganicCertifierSurvey/RequestCertifier/UpdateRequestCertifier'), ); -const ViewCertification = React.lazy(() => - import('../containers/OrganicCertifierSurvey/ViewCertification/ViewCertification'), +const ViewCertification = React.lazy( + () => import('../containers/OrganicCertifierSurvey/ViewCertification/ViewCertification'), ); const RenderSurvey = React.lazy(() => import('../containers/RenderSurvey/RenderSurvey')); const ExportDownload = React.lazy(() => import('../containers/ExportDownload')); -const ManagementTasks = React.lazy(() => - import('../containers/Crop/ManagementDetail/ManagementTasks'), +const ManagementTasks = React.lazy( + () => import('../containers/Crop/ManagementDetail/ManagementTasks'), ); -const ManagementDetails = React.lazy(() => - import('../containers/Crop/ManagementDetail/ManagementDetails'), +const ManagementDetails = React.lazy( + () => import('../containers/Crop/ManagementDetail/ManagementDetails'), ); -const EditManagementDetails = React.lazy(() => - import('../containers/Crop/ManagementDetail/EditManagementDetails'), +const EditManagementDetails = React.lazy( + () => import('../containers/Crop/ManagementDetail/EditManagementDetails'), ); -const CompleteManagementPlan = React.lazy(() => - import('../containers/Crop/CompleteManagementPlan/CompleteManagementPlan'), +const CompleteManagementPlan = React.lazy( + () => import('../containers/Crop/CompleteManagementPlan/CompleteManagementPlan'), ); -const AbandonManagementPlan = React.lazy(() => - import('../containers/Crop/CompleteManagementPlan/AbandonManagementPlan'), +const AbandonManagementPlan = React.lazy( + () => import('../containers/Crop/CompleteManagementPlan/AbandonManagementPlan'), ); const RepeatCropPlan = React.lazy(() => import('../containers/Crop/RepeatCropPlan')); -const RepeatCropPlanConfirmation = React.lazy(() => - import('../containers/Crop/RepeatCropPlan/Confirmation'), +const RepeatCropPlanConfirmation = React.lazy( + () => import('../containers/Crop/RepeatCropPlan/Confirmation'), ); const TaskAssignment = React.lazy(() => import('../containers/Task/TaskAssignment')); @@ -187,44 +190,44 @@ const Tasks = React.lazy(() => import('../containers/Task')); const ManageCustomTasks = React.lazy(() => import('../containers/Task/ManageCustomTasks')); const AddCustomTask = React.lazy(() => import('../containers/Task/AddCustomTask')); const TaskComplete = React.lazy(() => import('../containers/Task/TaskComplete')); -const HarvestCompleteQuantity = React.lazy(() => - import('../containers/Task/TaskComplete/HarvestComplete/Quantity'), +const HarvestCompleteQuantity = React.lazy( + () => import('../containers/Task/TaskComplete/HarvestComplete/Quantity'), ); -const HarvestUses = React.lazy(() => - import('../containers/Task/TaskComplete/HarvestComplete/HarvestUses'), +const HarvestUses = React.lazy( + () => import('../containers/Task/TaskComplete/HarvestComplete/HarvestUses'), ); const TaskCompleteStepOne = React.lazy(() => import('../containers/Task/TaskComplete/StepOne')); const TaskReadOnly = React.lazy(() => import('../containers/Task/TaskReadOnly')); const EditCustomTask = React.lazy(() => import('../containers/Task/EditCustomTask')); const TaskAbandon = React.lazy(() => import('../containers/Task/TaskAbandon')); // const EditCustomTaskUpdate = React.lazy(() => import('../containers/Task/EditCustomTaskUpdate')); -const TaskTransplantMethod = React.lazy(() => - import('../containers/Task/TaskTransplantMethod/TaskTransplantMethod'), +const TaskTransplantMethod = React.lazy( + () => import('../containers/Task/TaskTransplantMethod/TaskTransplantMethod'), ); -const TaskBedMethod = React.lazy(() => - import('../containers/Task/TaskTransplantMethod/TaskBedMethod'), +const TaskBedMethod = React.lazy( + () => import('../containers/Task/TaskTransplantMethod/TaskBedMethod'), ); -const TaskBedGuidance = React.lazy(() => - import('../containers/Task/TaskTransplantMethod/TaskBedGuidance'), +const TaskBedGuidance = React.lazy( + () => import('../containers/Task/TaskTransplantMethod/TaskBedGuidance'), ); -const TaskRowMethod = React.lazy(() => - import('../containers/Task/TaskTransplantMethod/TaskRowMethod'), +const TaskRowMethod = React.lazy( + () => import('../containers/Task/TaskTransplantMethod/TaskRowMethod'), ); -const TaskRowGuidance = React.lazy(() => - import('../containers/Task/TaskTransplantMethod/TaskRowGuidance'), +const TaskRowGuidance = React.lazy( + () => import('../containers/Task/TaskTransplantMethod/TaskRowGuidance'), ); -const TaskContainerMethod = React.lazy(() => - import('../containers/Task/TaskTransplantMethod/TaskContainerMethod'), +const TaskContainerMethod = React.lazy( + () => import('../containers/Task/TaskTransplantMethod/TaskContainerMethod'), ); const SensorList = React.lazy(() => import('../containers/SensorList')); const SensorReadings = React.lazy(() => import('../containers/SensorReadings/v2')); const IrrigationPrescription = React.lazy(() => import('../containers/IrrigationPrescription')); const Notification = React.lazy(() => import('../containers/Notification')); -const NotificationReadOnly = React.lazy(() => - import('../containers/Notification/NotificationReadOnly'), +const NotificationReadOnly = React.lazy( + () => import('../containers/Notification/NotificationReadOnly'), ); -const UnknownRecord = React.lazy(() => - import('../containers/ErrorHandler/UnknownRecord/UnknownRecord'), +const UnknownRecord = React.lazy( + () => import('../containers/ErrorHandler/UnknownRecord/UnknownRecord'), ); const Routes = ({ isCompactSideMenu }) => { @@ -511,7 +514,7 @@ const Routes = ({ isCompactSideMenu }) => { } /> } /> - + } /> } /> @@ -842,7 +845,7 @@ const Routes = ({ isCompactSideMenu }) => { } /> } /> - + } /> } /> diff --git a/packages/webapp/src/store/actionTypes.js b/packages/webapp/src/store/actionTypes.js index 85d64b64f8..dc7f744fdd 100644 --- a/packages/webapp/src/store/actionTypes.js +++ b/packages/webapp/src/store/actionTypes.js @@ -13,6 +13,11 @@ * GNU General Public License for more details, see . */ +import { createAction } from '@reduxjs/toolkit'; + export const ActionTypes = { - SWITCH_FARMS: 'chooseFarmFlowReducer/startSwitchFarmModal', + RESET_FARM_STATE: 'farmStateReducer/reset', }; + +// Dispatched by clearOldFarmStateSaga (switch, add, and invite) +export const resetFarmStateReducer = createAction(ActionTypes.RESET_FARM_STATE); diff --git a/packages/webapp/src/store/api/apiTags.ts b/packages/webapp/src/store/api/apiTags.ts index dd0f96c5b0..d80d7b745c 100644 --- a/packages/webapp/src/store/api/apiTags.ts +++ b/packages/webapp/src/store/api/apiTags.ts @@ -55,7 +55,7 @@ export const FarmTags = [ 'SensorReadings', 'Weather', 'MarketDirectoryInfo', - 'TapeSurvey', + 'SurveyResponse', 'FarmNote', 'FarmNotesRead', ] as const; diff --git a/packages/webapp/src/store/api/tapeSurveyApi.ts b/packages/webapp/src/store/api/surveyApi.ts similarity index 58% rename from packages/webapp/src/store/api/tapeSurveyApi.ts rename to packages/webapp/src/store/api/surveyApi.ts index f8d04d8dae..d92a66d4c6 100644 --- a/packages/webapp/src/store/api/tapeSurveyApi.ts +++ b/packages/webapp/src/store/api/surveyApi.ts @@ -14,31 +14,33 @@ */ import { api } from './apiSlice'; -import { tapeSurveyUrl } from '../../apiConfig'; +import { surveyResponseUrl } from '../../apiConfig'; import { DO_CDN_URL } from '../../util/constants'; -export interface TapeSurveyRecord { +export interface SurveyResponseRecord { id: string; farm_id: string; + survey_key: string; survey_response: Record; survey_version: string; project_id: string; survey_step: string; } -export interface AddTapeSurveyReqBody { +export interface AddSurveyResponseReqBody { farm_id: string; + survey_key: string; survey_response: Record; } -export const tapeSurveyApi = api.injectEndpoints({ +export const surveyApi = api.injectEndpoints({ endpoints: (build) => ({ // Fetches the SurveyJS JSON definition from DO CDN. // Uses queryFn (not query) because this bypasses the LiteFarm API base URL and auth headers. - getTapeSurveyJson: build.query, string>({ - queryFn: async (versionKey) => { + getSurveyJson: build.query, { cdnDirectory: string; version: string }>({ + queryFn: async ({ cdnDirectory, version }) => { try { - const response = await fetch(`${DO_CDN_URL}/tape_surveys/${versionKey}.json`); + const response = await fetch(`${DO_CDN_URL}/${cdnDirectory}/${version}.json`); if (!response.ok) { return { error: { status: response.status, data: `Failed to fetch survey JSON` }, @@ -51,24 +53,29 @@ export const tapeSurveyApi = api.injectEndpoints({ } }, }), - getTapeSurvey: build.query({ - query: () => `${tapeSurveyUrl}`, - providesTags: ['TapeSurvey'], + getLatestSurveyResponse: build.query({ + query: ({ surveyKey }) => ({ + url: surveyResponseUrl, + params: { survey_key: surveyKey }, + }), + providesTags: (_result, _error, { surveyKey }) => [{ type: 'SurveyResponse', id: surveyKey }], }), - addTapeSurvey: build.mutation({ + addSurveyResponse: build.mutation({ query: (body) => ({ - url: tapeSurveyUrl, + url: surveyResponseUrl, method: 'POST', body, }), - invalidatesTags: ['TapeSurvey'], + invalidatesTags: (_result, _error, { survey_key }) => [ + { type: 'SurveyResponse', id: survey_key }, + ], }), }), }); export const { - useGetTapeSurveyJsonQuery, - useGetTapeSurveyQuery, - useAddTapeSurveyMutation, + useGetSurveyJsonQuery, + useGetLatestSurveyResponseQuery, + useAddSurveyResponseMutation, usePrefetch, -} = tapeSurveyApi; +} = surveyApi; diff --git a/packages/webapp/src/store/reducer.js b/packages/webapp/src/store/reducer.js index 5987ca8a97..97a4543d68 100644 --- a/packages/webapp/src/store/reducer.js +++ b/packages/webapp/src/store/reducer.js @@ -71,7 +71,7 @@ import fieldWorkTypeReducer from '../containers/fieldWorkTypeSlice'; import irrigationTaskReducer from '../containers/slice/taskSlice/irrigationTaskSlice'; import irrigationTaskTypesReducer from '../containers/irrigationTaskTypesSlice'; import revenueTypeReducer from '../containers/revenueTypeSlice'; -import tapeSurveyReducer from '../containers/Insights/TapeSurvey/tapeSurveySlice'; +import surveyDraftReducer from '../containers/Insights/Survey/surveyDraftSlice'; import { ActionTypes } from './actionTypes'; // all the initial state for the forms @@ -183,7 +183,7 @@ const entitiesReducer = combineReducers({ const farmStateReducer = combineReducers({ notificationReducer, - tapeSurveyReducer, + surveyDraftReducer, }); const persistedStateReducer = combineReducers({ @@ -231,8 +231,8 @@ const appReducer = combineReducers({ }); const rootReducer = (state, action) => { - if (state && action.type === ActionTypes.SWITCH_FARMS) { - // selectively only reset farmStateReducer state when switching farms + if (state && action.type === ActionTypes.RESET_FARM_STATE) { + // Drop the farmStateReducer branch so combineReducers re-initialises it const { farmStateReducer, ...otherReducers } = state; state = otherReducers; } diff --git a/packages/webapp/src/stories/Finances/RevenueForm.stories.jsx b/packages/webapp/src/stories/Finances/RevenueForm.stories.jsx index 2f7302c78d..b83fad9c36 100644 --- a/packages/webapp/src/stories/Finances/RevenueForm.stories.jsx +++ b/packages/webapp/src/stories/Finances/RevenueForm.stories.jsx @@ -17,6 +17,8 @@ import RevenueForm from '../../components/Forms/RevenueForm'; import { getEntityTypeDefaultValues } from '../../containers/Finances/EntitySaleInputs'; import { componentDecorators } from '../Pages/config/Decorators'; +const system = 'metric'; + const cropSale = { sale_id: 17, customer_name: 'Name', @@ -207,7 +209,7 @@ CropSaleDetail.args = { revenueTypeOptions, onRetire: () => {}, revenueTypes, - entitySaleDefaultValues: getEntityTypeDefaultValues(cropSale, 'crop'), + entitySaleDefaultValues: getEntityTypeDefaultValues(cropSale, 'crop', system), }; export const AnimalSaleDetail = Template.bind({}); @@ -218,5 +220,5 @@ AnimalSaleDetail.args = { revenueTypeOptions, onRetire: () => {}, revenueTypes, - entitySaleDefaultValues: getEntityTypeDefaultValues(animalSale, 'animal'), + entitySaleDefaultValues: getEntityTypeDefaultValues(animalSale, 'animal', system), }; diff --git a/packages/webapp/src/util/smartIrrigation.ts b/packages/webapp/src/util/smartIrrigation.ts index 3a1b0ff9ff..14d98d107a 100644 --- a/packages/webapp/src/util/smartIrrigation.ts +++ b/packages/webapp/src/util/smartIrrigation.ts @@ -37,5 +37,5 @@ export const createESciReportLink = ({ return; } - return `https://app.esci.io/${organisation_url_name}/${system_url_name}/irrigation-report`; + return `https://app.esci.io/${organisation_url_name}/reports/${system_url_name}`; };