From a234b3531d6d3da4119848f6629feb5aece5dd68 Mon Sep 17 00:00:00 2001 From: John Cardinal Date: Fri, 6 Mar 2020 19:36:36 +0000 Subject: [PATCH] Locale -> Translation --- .vscode/launch.json | 4 +- devdocs/coding-standards.txt | 6 +- devdocs/specs/core-generator.txt | 2 +- devdocs/specs/core-import-v7.txt | 2 +- .../core-list-graph-datatable-filter-sort.txt | 4 +- devdocs/specs/core-main-grids.txt | 4 +- devdocs/specs/core-roles.txt | 2 +- devdocs/specs/core-testing.txt | 2 +- ...-localization.txt => core-translation.txt} | 52 ++-- devdocs/specs/core-ui-design.txt | 2 +- devdocs/todo.txt | 20 +- devdocs/tools.txt | 2 +- docs/8.0/ayanova/docs/api-request-format.md | 6 +- docs/8.0/ayanova/docs/ay-locale.md | 16 -- docs/8.0/ayanova/docs/ay-translation.md | 16 ++ ...alized-text.md => form-adm-translation.md} | 0 ...ome-locale.md => form-home-translation.md} | 2 +- .../ayanova/docs/form-home-user-settings.md | 2 +- ...e.md => ops-config-default-translation.md} | 20 +- .../docs/ops-config-environment-variables.md | 4 +- docs/8.0/ayanova/docs/ops-error-codes.md | 2 +- docs/8.0/ayanova/mkdocs.yml | 8 +- linecounts/linecount.txt | 2 +- ...ext.cs => UserTranslationIdFromContext.cs} | 6 +- .../AyaNova/Controllers/ApiRootController.cs | 2 +- .../Controllers/AttachmentController.cs | 5 +- .../Controllers/EnumPickListController.cs | 60 ++--- .../AyaNova/Controllers/SearchController.cs | 2 +- ...Controller.cs => TranslationController.cs} | 125 ++++----- .../DataListSqlFilterCriteriaBuilder.cs | 2 +- server/AyaNova/Program.cs | 2 +- server/AyaNova/Startup.cs | 11 +- server/AyaNova/biz/AyaEvent.cs | 2 +- server/AyaNova/biz/AyaType.cs | 2 +- server/AyaNova/biz/BizObject.cs | 2 +- server/AyaNova/biz/BizObjectFactory.cs | 12 +- server/AyaNova/biz/BizRoles.cs | 8 +- server/AyaNova/biz/DataListViewBiz.cs | 14 +- server/AyaNova/biz/FormCustomBiz.cs | 16 +- server/AyaNova/biz/ImportAyaNova7Biz.cs | 8 +- server/AyaNova/biz/PrimeData.cs | 42 +-- server/AyaNova/biz/Search.cs | 91 +++---- .../biz/{LocaleBiz.cs => TranslationBiz.cs} | 251 +++++++++--------- server/AyaNova/biz/UserBiz.cs | 52 ++-- server/AyaNova/biz/WidgetBiz.cs | 10 +- server/AyaNova/models/AyContext.cs | 10 +- server/AyaNova/models/Locale.cs | 12 +- server/AyaNova/models/LocaleItem.cs | 6 +- server/AyaNova/models/User.cs | 2 +- server/AyaNova/resource/de.json | 26 +- server/AyaNova/resource/en.json | 28 +- server/AyaNova/resource/es.json | 26 +- server/AyaNova/resource/fr.json | 26 +- server/AyaNova/util/AySchema.cs | 18 +- server/AyaNova/util/FileUtil.cs | 2 +- server/AyaNova/util/Seeder.cs | 16 +- server/AyaNova/util/ServerBootConfig.cs | 30 +-- startserver.bat | 2 +- 58 files changed, 540 insertions(+), 569 deletions(-) rename devdocs/specs/{core-localization.txt => core-translation.txt} (63%) delete mode 100644 docs/8.0/ayanova/docs/ay-locale.md create mode 100644 docs/8.0/ayanova/docs/ay-translation.md rename docs/8.0/ayanova/docs/{form-adm-localized-text.md => form-adm-translation.md} (100%) rename docs/8.0/ayanova/docs/{form-home-locale.md => form-home-translation.md} (68%) rename docs/8.0/ayanova/docs/{ops-config-default-language.md => ops-config-default-translation.md} (72%) rename server/AyaNova/ControllerHelpers/{UserLocaleIdFromContext.cs => UserTranslationIdFromContext.cs} (64%) rename server/AyaNova/Controllers/{LocaleController.cs => TranslationController.cs} (65%) rename server/AyaNova/biz/{LocaleBiz.cs => TranslationBiz.cs} (64%) diff --git a/.vscode/launch.json b/.vscode/launch.json index 17ec1dc0..06b57c46 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -42,8 +42,8 @@ "AYANOVA_JWT_SECRET": "UNLICENSED5G*QQJ8#bQ7$Xr_@sXfHq4", "AYANOVA_LOG_LEVEL": "Info", //"AYANOVA_LOG_LEVEL": "Debug", - "AYANOVA_DEFAULT_LANGUAGE": "en", - //LOCALE MUST BE en for Integration TESTING + "AYANOVA_DEFAULT_TRANSLATION": "en", + //TRANSLATION MUST BE en for Integration TESTING //"AYANOVA_PERMANENTLY_ERASE_DATABASE": "true", "AYANOVA_DB_CONNECTION": "Server=localhost;Username=postgres;Password=raven;Database=AyaNova;", "AYANOVA_USE_URLS": "http://*:7575;", diff --git a/devdocs/coding-standards.txt b/devdocs/coding-standards.txt index c389eb78..454076f1 100644 --- a/devdocs/coding-standards.txt +++ b/devdocs/coding-standards.txt @@ -12,7 +12,7 @@ Error messages / Numbers - Look for English text in all the messages so far and see if can be localized even crudely by google translate and do so - Make sure error numbers have a consistent system and don't conflict, I think there are two sets of error numbers, there should only be one - Make sure Every error has a number and that is documented in the manual - - Locale keys for error numbers?? i.e. E1000, "blah blah error 1000" + - Translation keys for error numbers?? i.e. E1000, "blah blah error 1000" C# code convention: All names are PascalCaseOnly with the following two exceptions: @@ -24,8 +24,8 @@ C# code convention: DATES, TIMES, TIMESTAMPS - All dates and times sent or retrieved from the REST interface must be in UTC / GMT time zone. It is the client's responsibility to display and accept dates in local format but interaction with the server is in UTC only. -Localized text - All text prsented by the server will be a locale key only and it is the clients responsibility to display in local text format with the exception of: - - Ops logs, Metrics, event logs: these items and any other future pre-generated text items will be localized at the server according to the logged in users' locale +Localized text - All text prsented by the server will be a translation key only and it is the clients responsibility to display in local text format with the exception of: + - Ops logs, Metrics, event logs: these items and any other future pre-generated text items will be localized at the server according to the logged in users' translation JAVASCRIPT diff --git a/devdocs/specs/core-generator.txt b/devdocs/specs/core-generator.txt index abb30259..3ce97aea 100644 --- a/devdocs/specs/core-generator.txt +++ b/devdocs/specs/core-generator.txt @@ -87,7 +87,7 @@ DeliverNotifications (techs) /// foreach NotifyEventRecord it adds a NotificationListInfo /// for each open delivery window for each subscriber to that event /// As it Processes each deliverable notification it formats it to users - /// locale and preferences for size etc and keeps track of the address and + /// translation and preferences for size etc and keeps track of the address and /// delivery type. /// /// diff --git a/devdocs/specs/core-import-v7.txt b/devdocs/specs/core-import-v7.txt index e5a03006..b974e6b3 100644 --- a/devdocs/specs/core-import-v7.txt +++ b/devdocs/specs/core-import-v7.txt @@ -73,7 +73,7 @@ NOTES FOR DOCS - Only an empty database is supported for import - Only one shot import, can't import again later - LOCALES - - MUST be a default locale set before import because new raven keys will be added to imported v7 locale using the default locale only + - MUST be a default translation set before import because new raven keys will be added to imported v7 translation using the default translation only - IMPORTED USERS - In order to ensure security imported users are not imported ready to login but rather must be edited individually after import: - All users are imported with Active status set to false and must be individually edited and set to Active=true as required diff --git a/devdocs/specs/core-list-graph-datatable-filter-sort.txt b/devdocs/specs/core-list-graph-datatable-filter-sort.txt index 7c3a1729..27473447 100644 --- a/devdocs/specs/core-list-graph-datatable-filter-sort.txt +++ b/devdocs/specs/core-list-graph-datatable-filter-sort.txt @@ -153,7 +153,7 @@ Two types of filters Named or Default: - This is a client issue, Server doesn't care what the filters are called adn has no special processing for default filters Named filters can be made public or personal. If public then all users with rights to that object can see them, personal are always only personal. Filter is constructed from an FILTEROPTIONS object fetched from the server list route that has a list type name which is unique to that list route -and also lists all the fields filterable, their type and the locale key to display it +and also lists all the fields filterable, their type and the translation key to display it - e.g.: {ListKey:"widget",fields:[{fld:"name",lt:"WidgetName",type:"text"},{fld:"dollarAmount",lt:"WidgetDollarAmount",type:"currency"}]} - List key Certain types have extended abilities, for example dates have the classic floating AyaNova date ranges pre-defined or specific dates @@ -186,7 +186,7 @@ Upon user selecting a filter to use the list query string has the regular paging -------------------------------------------------------- NOTES ABOUT WHY I DID THE FILTEROPTIONS LIKE I DID: -//Need a collection of fields and types and locale keys for +//Need a collection of fields and types and translation keys for // - Client fetching filteroptions via list class // - Just a static list of items localized and sent to the client // - DataFilter validation via list class diff --git a/devdocs/specs/core-main-grids.txt b/devdocs/specs/core-main-grids.txt index b23afe6d..fcfec38d 100644 --- a/devdocs/specs/core-main-grids.txt +++ b/devdocs/specs/core-main-grids.txt @@ -7,7 +7,7 @@ Proposed system is a hybrid grid system that has two modes to take into account - In this mode only one column shows and it's formatted according to the Display Format Template - DisplayFormatTemplate is specd in the core-display-format-template-system.txt doc - So the user chooses which columns to show in a small factor themselves, default is name only or equivalent - - As the client already does all the presentation and locale formatting it will also handle mini column concatenation + - As the client already does all the presentation and translation formatting it will also handle mini column concatenation - The server's responsibility for mini is to use the mini format template which may well have different columns defined than the full - Return the data just the same as for the wide template but it's very likely different data @@ -62,7 +62,7 @@ Server - Optional: ID value (if the object is openable **** MUST CHECK RIGHTS ALSO HERE **** then this is the id to open for the client to put a hyperlink on that column) - To save bandwidth abbreviations are used in the column definitions: - ColumnsJSON=@"""columns"":[ {""cm"":""Widget"",""dt"":""text"",""ay"":"+ AyaType.Widget.ToString()+ "}]"; - - cm=column name locale key, dt=AyDataType, ay=AyaType to open on click of that column field (optional, not present if not openable) + - cm=column name translation key, dt=AyDataType, ay=AyaType to open on click of that column field (optional, not present if not openable) - rid flagged column in each row is *ALWAYS* the rowID column specified in objectfields with it's sql attributes - For example (wide list): data:{ diff --git a/devdocs/specs/core-roles.txt b/devdocs/specs/core-roles.txt index a21c22bc..b67ebb98 100644 --- a/devdocs/specs/core-roles.txt +++ b/devdocs/specs/core-roles.txt @@ -259,7 +259,7 @@ BizAdminLimited | BizAdminFull | DispatchLimited | DispatchFull | InventoryLimit - Schedule - Memos - Reminders - - Locale settings for User + - Translation settings for User - Set login and password - Notification subscriptions diff --git a/devdocs/specs/core-testing.txt b/devdocs/specs/core-testing.txt index 2ea81663..be05e080 100644 --- a/devdocs/specs/core-testing.txt +++ b/devdocs/specs/core-testing.txt @@ -13,4 +13,4 @@ FRONT-END - Integration tests that excercise the front end and ensure things appear where they are supposed to given certain tasks - Ideally it would be able to run a set of business tasks against the UI and confirm at each point like make a rando customer and then a workorder and on - Something that we can leave running for a long period of time to verify load and no leaks - - MUST cause all locale keys required *anywhere* in the UI to be requested one way or another so that I get a valid list of used keys so I can winnow out the unused ones \ No newline at end of file + - MUST cause all translation keys required *anywhere* in the UI to be requested one way or another so that I get a valid list of used keys so I can winnow out the unused ones \ No newline at end of file diff --git a/devdocs/specs/core-localization.txt b/devdocs/specs/core-translation.txt similarity index 63% rename from devdocs/specs/core-localization.txt rename to devdocs/specs/core-translation.txt index 2d343bfc..e644d970 100644 --- a/devdocs/specs/core-localization.txt +++ b/devdocs/specs/core-translation.txt @@ -1,52 +1,52 @@ -# Localization specifications +# Translation specifications REQUIREMENTS - ROLE RIGHTS: BizAdminFull only can edit. BizAdminLimited can view but not change - - CENTRAL LOCALE EDIT FORM - - End user customizes localizations from a central location with a kick ass search and change ability - - We will *not* support localization changes form by form as in v7 but only from central location + - CENTRAL translation EDIT FORM + - End user customizes Translations from a central location with a kick ass search and change ability + - We will *not* support Translation changes form by form as in v7 but only from central location - Faster to code TTM - User doesn't think they are only changing it on one form only - Some forms don't have all the related keys on them (i.e. a list will show "Widgets" even though the edit form never shows that string) - - Client handles *ALL* localization presentation locally, only exception is the server ops logs + - Client handles *ALL* Translation presentation locally, only exception is the server ops logs - This saves bandwidth and hassle and leaves presentation to the client where it belongs (was a source of trouble in v7) - Keys are text, human readable and as short as possible - Not numeric ID's for these, strictly textual - values may have substitution tokens in them for certain things - - DataDump plugin will export and import any custom locales that did not come with AyaNova 7 - - Dump needs to check if the "stock" locale has been edited or not before exporting + - DataDump plugin will export and import any custom translations that did not come with AyaNova 7 + - Dump needs to check if the "stock" translation has been edited or not before exporting - Only edited ones are exported - - For example if someone edited the Spanish locale then it would dump as "Spanish-Custom" (or whatever the word for custom is in that language) so as not to interfere with our stock Built in Spanish in Raven - - The documented renaming (below) will need to be automated during import of v7 stock locales to migrate to the new key values - - Two kinds of locales: Stock and Custom. - - Stock locales are stored in db and not user editable - - STock locale names are whatever the international name for that locale is like "esp" or "fr" etc - - Custom locales are stored in the database and are user customizable + - For example if someone edited the Spanish translation then it would dump as "Spanish-Custom" (or whatever the word for custom is in that language) so as not to interfere with our stock Built in Spanish in Raven + - The documented renaming (below) will need to be automated during import of v7 stock translations to migrate to the new key values + - Two kinds of translations: Stock and Custom. + - Stock translations are stored in db and not user editable + - STock translation names are whatever the international name for that translation is like "esp" or "fr" etc + - Custom translations are stored in the database and are user customizable ROUTES - - GET ROUTE that provides a pick list of locales + - GET ROUTE that provides a pick list of translations - - GET ROUTE that returns all key value pairs when requested for a specific locale + - GET ROUTE that returns all key value pairs when requested for a specific translation - This one is for editing purposes or for export to disk - - GET ROUTE that returns a list of specific key value pairs for a requested locale and specific list of locale keys provided + - GET ROUTE that returns a list of specific key value pairs for a requested translation and specific list of translation keys provided - This one is for day to day ops and will be called on any client opening a new area of UI they have not previously opened - - PUT ROUTE that accepts a list of key value pairs and a specific locale and updates the current values in db from the provided list - - if locale name key provided is one of our stock ones then it errors out as you can't change the stock locales - - if locale doesn't exist in db errors out + - PUT ROUTE that accepts a list of key value pairs and a specific translation and updates the current values in db from the provided list + - if translation name key provided is one of our stock ones then it errors out as you can't change the stock translations + - if translation doesn't exist in db errors out - biz full rights only - - POST ROUTE that creates a new locale duplicated from an existing locale and copies all the values from the existing locale - - Post object {sourceLocale:"English", newLocale:"MyLocale"} + - POST ROUTE that creates a new translation duplicated from an existing translation and copies all the values from the existing translation + - Post object {sourcetranslation:"English", newtranslation:"Mytranslation"} - Errors if already exists with that name - Sets it to stock=false so it can be edited - - This is also how you rename a locale + - This is also how you rename a translation - - DELETE ROUTE for deleting any non-stock locale - - Can't delete current DB default locale (specfic error) - - Users of that locale will be reset to current DB default locale + - DELETE ROUTE for deleting any non-stock translation + - Can't delete current DB default translation (specfic error) + - Users of that translation will be reset to current DB default translation @@ -91,7 +91,7 @@ CLIENT - client checks local cache (do I have the values for the list of required keys??) - YES: just use it - NO: Send a list of keys to the server along with the user id that are required for this form and get back the LT, put it in the cache - - User id required because someone might edit their locale or the locale name and so it needs to check via the user account what the locale is + - User id required because someone might edit their translation or the translation name and so it needs to check via the user account what the translation is This way there is no wasted space at the client caching stuff that will never be used diff --git a/devdocs/specs/core-ui-design.txt b/devdocs/specs/core-ui-design.txt index b1e79c87..b6723964 100644 --- a/devdocs/specs/core-ui-design.txt +++ b/devdocs/specs/core-ui-design.txt @@ -43,7 +43,7 @@ Requirements - MEMOS (for user) - SCHEDULE MARKERS (list for user, convenience extra so don't need to hunt around on calendar) - SETTINGS - - User locale settings + - User translation settings - Any other user specific settings that the User can control (and sb able to control more than in v7 if it doesn't affect anyone else) - Change login? - notification subscriptions diff --git a/devdocs/todo.txt b/devdocs/todo.txt index 21332935..bb69d89a 100644 --- a/devdocs/todo.txt +++ b/devdocs/todo.txt @@ -4,6 +4,8 @@ ## IMMEDIATE ITEMS +TODO: DataDump plugin make sure locale export json files are named "translation" instead as raven only sees "translation" when importing + TODO: BizRoles.cs seems to get hammered on every single request, is it efficient? - Why is it not cached in some way? @@ -21,8 +23,8 @@ TODO: 2019-06-07 10:47:57.8894|WARN|Microsoft.AspNetCore.Cors.Infrastructure.Cor Configure the policy by listing individual origins if credentials needs to be supported. TODO: "Client" -> "Customer " all languages but english need translated whatever was translated for "Client" text to whatever is now that languages "Customer" text (did english only for dev purposes) -TODO: "Service workorders" now "workorders" do for non english locales, keys changed are: GlobalWorkorderNumberStartSeed, WorkorderServiceTemplate, GlobalUseInventoryDescription, GlobalUnitNameDisplayFormatsDescription, WorkorderServiceList - - Also a shit ton more todo in all locales including english - just search for Service workorder case insensitive to see a bunch (in english anyway) +TODO: "Service workorders" now "workorders" do for non english translations, keys changed are: GlobalWorkorderNumberStartSeed, WorkorderServiceTemplate, GlobalUseInventoryDescription, GlobalUnitNameDisplayFormatsDescription, WorkorderServiceList + - Also a shit ton more todo in all translations including english - just search for Service workorder case insensitive to see a bunch (in english anyway) TODO: Need to burn test for memory leaks @@ -64,7 +66,7 @@ TODO: Two kinds of mass fetch records in RAVEN - ACTION required: - Make sure the server supports this -TODO: locale cjkindex, no way to set this value currently +TODO: translation cjkindex, no way to set this value currently TODO: Licensing - make sure tech type use license works properly: a tech license is consumed if a user has **any one** of the four roles of TechFull, TechLimited, SubcontractorFull, SubcontractorLimited ### TODO FILTER ISSUE: SEE integration tests search for BUGBUG there are two tests failing in DataFilterFilteringLists tests that might be DST related @@ -82,7 +84,7 @@ TODO: Need client docs at server end just for client user - I just don't want the hassle of setting up another build process for client docs and folders and shit right now TODO: UNLOCALIZED TEXT - - Look for old locale text keys that were not translated, there are more than a few keys that were added later to v7 and never translated out of english. + - Look for old translation text keys that were not translated, there are more than a few keys that were added later to v7 and never translated out of english. - Some may never be used so be careful about this. - Unused keys won't be taking up any bandwidth so maybe this is a non-issue but you never know if I might need something in future as well so...tricky, maybe this is a 2.0 thing @@ -217,7 +219,7 @@ Once I can make the client I need to get into that and make the shell and initia - Login , logout - License - Security / rights - - See localized text / change locale + - See localized text / change translation later - Widget CRUD and lists @@ -269,12 +271,12 @@ MISC FUTURE ITEMS NOT SURE ABOUT THAT CAME UP DURING CODING / TESTING - LOCALIZED TEXT - Localized text keys would be nice if they are understandable as is for API direct users so you don't need to be in the client to understand what's happening - - Need a locale indepedent locale so that server errors without a corresponding user are localized to default english - - Also maybe a locale can be chosen at the server for error messages since we'll go by code numbers anyway. + - Need a translation indepedent translation so that server errors without a corresponding user are localized to default english + - Also maybe a translation can be chosen at the server for error messages since we'll go by code numbers anyway. - Starting to get to the point where I'll need this, i.e. error messages and logs that are part of core ops but need to be displayed in the UI - - Need to go through the api and find all the plain text messages returned and convert to locale text keys + - Need to go through the api and find all the plain text messages returned and convert to translation text keys - Ensure every error message has an error number of one kind or another and that they are not conflicted and easy to sort out if coming from server or api or etc - - Need to suck out our paid for translations and convert them into new locale text format + - Need to suck out our paid for translations and convert them into new translation text format - DataDump?? - REPORTING diff --git a/devdocs/tools.txt b/devdocs/tools.txt index f1852a68..ea20e350 100644 --- a/devdocs/tools.txt +++ b/devdocs/tools.txt @@ -576,5 +576,5 @@ Use the credentials specified for postgres which is username postgres and passwo TRANSLATIONS / TRANSLATE / LOCALIZATION / LOCALE -Microsoft handy dandy product locale search database site: https://www.microsoft.com/en-us/language/Search +Microsoft handy dandy product translation search database site: https://www.microsoft.com/en-us/language/Search Google translate to verify: https://translate.google.com/ \ No newline at end of file diff --git a/docs/8.0/ayanova/docs/api-request-format.md b/docs/8.0/ayanova/docs/api-request-format.md index 8fda8110..6aa15f46 100644 --- a/docs/8.0/ayanova/docs/api-request-format.md +++ b/docs/8.0/ayanova/docs/api-request-format.md @@ -21,11 +21,11 @@ The [API explorer console](api-console.md) on your server is always the best sou All dates and times sent or retrieved from the REST interface **must** be in UTC / GMT time zone. It is the Client software's responsibility to display and accept input of dates in local format but all dates transmitted to or received from the server must be in is0-8601 UTC time zone format only. For example: `2018-12-19T17:54:13.616028`. Note there is no time zone offset, the time is understood to be UTC already. -## Localization +## Translation -Every User account in AyaNova has their own UserOptions object which contains their personal localization settings such as time zone offset, currency symbol and numeric formatting options you can use this value to correctly display and interpret values at a client level. +Every User account in AyaNova has their own UserOptions object which contains their personal Translation settings such as time zone offset, currency symbol and numeric formatting options you can use this value to correctly display and interpret values at a client level. -In addition every user has their own LocaleId setting stored in their User record (not UserOptions) which can be used to fetch and display text in the correct locale by using the methods in the Locale routes. +In addition every user has their own TranslationId setting stored in their User record (not UserOptions) which can be used to fetch and display text in the correct translation by using the methods in the Translation routes. ## Paging, sorting and filtering lists diff --git a/docs/8.0/ayanova/docs/ay-locale.md b/docs/8.0/ayanova/docs/ay-locale.md deleted file mode 100644 index 01b70bba..00000000 --- a/docs/8.0/ayanova/docs/ay-locale.md +++ /dev/null @@ -1,16 +0,0 @@ -# LOCALE - -The Locale feature controls the text displayed in the AyaNova user interface. -The primary purpose is to provide the AyaNova user interface in various languages however it is also used to customize text displayed to conform to specific terminology used by a business. -For example a property management company may prefer the term "Apartment" rather than the generic term "Unit" provided by AyaNova. - -## Stock locales -AyaNova comes with predefined locale translations for `English`, `French`, `Spanish` and `German` - -## Setting the locale -There are two places to set locales: -A default server [AYANOVA_DEFAULT_LANGUAGE](ops-config-default-language.md) setting used to control the default Locale used. - - -TODO: USER SETTING FOR LOCALE - diff --git a/docs/8.0/ayanova/docs/ay-translation.md b/docs/8.0/ayanova/docs/ay-translation.md new file mode 100644 index 00000000..788113ec --- /dev/null +++ b/docs/8.0/ayanova/docs/ay-translation.md @@ -0,0 +1,16 @@ +# TRANSLATION + +The Translation feature controls the text displayed in the AyaNova user interface. +The primary purpose is to provide the AyaNova user interface in various languages however it is also used to customize text displayed to conform to specific terminology used by a business. +For example a property management company may prefer the term "Apartment" rather than the generic term "Unit" provided by AyaNova. + +## Stock translations +AyaNova comes with predefined translations for `English`, `French`, `Spanish` and `German` + +## Setting the translation +There are two places to set translations: +A default server [AYANOVA_DEFAULT_TRANSLATION](ops-config-default-language.md) setting used to control the default Translation used. + + +TODO: USER SETTING FOR TRANSLATION + diff --git a/docs/8.0/ayanova/docs/form-adm-localized-text.md b/docs/8.0/ayanova/docs/form-adm-translation.md similarity index 100% rename from docs/8.0/ayanova/docs/form-adm-localized-text.md rename to docs/8.0/ayanova/docs/form-adm-translation.md diff --git a/docs/8.0/ayanova/docs/form-home-locale.md b/docs/8.0/ayanova/docs/form-home-translation.md similarity index 68% rename from docs/8.0/ayanova/docs/form-home-locale.md rename to docs/8.0/ayanova/docs/form-home-translation.md index dbd1b62a..145b392f 100644 --- a/docs/8.0/ayanova/docs/form-home-locale.md +++ b/docs/8.0/ayanova/docs/form-home-translation.md @@ -1,3 +1,3 @@ -# HOME-LOCALE Placeholder +# HOME-TRANSLATION Placeholder This is a placeholder page for sections that are not written yet diff --git a/docs/8.0/ayanova/docs/form-home-user-settings.md b/docs/8.0/ayanova/docs/form-home-user-settings.md index ff527473..271666cc 100644 --- a/docs/8.0/ayanova/docs/form-home-user-settings.md +++ b/docs/8.0/ayanova/docs/form-home-user-settings.md @@ -38,7 +38,7 @@ This setting is provided for the purpose of forcing a browser to use a different If no language can be determined from the browser and no override has been set AyaNova will default to English USA - "en-US". -NOTE: This is a separate and unrelated setting to the users [Locale](ay-locale.md) setting which controls the set of customizable text used by AyaNova to display to the user. +NOTE: This is a separate and unrelated setting to the users [Translation](ay-translation.md) setting which controls the set of customizable text used by AyaNova to display to the user. ## Time Zone override The *required* Time Zone setting controls how date and time values are displayed, accepted for input and very importantly **converted** to local time from UTC time. diff --git a/docs/8.0/ayanova/docs/ops-config-default-language.md b/docs/8.0/ayanova/docs/ops-config-default-translation.md similarity index 72% rename from docs/8.0/ayanova/docs/ops-config-default-language.md rename to docs/8.0/ayanova/docs/ops-config-default-translation.md index 4ea34fb3..1030821b 100644 --- a/docs/8.0/ayanova/docs/ops-config-default-language.md +++ b/docs/8.0/ayanova/docs/ops-config-default-translation.md @@ -1,4 +1,4 @@ -# DEFAULT LANGUAGE / LOCALE SETTING +# DEFAULT TRANSLATION SETTING This setting controls the default language for text displayed to users in the AyaNova user interface. @@ -8,7 +8,7 @@ It will also be used for some messages that originate at the server and are not ## Default -If no language is specified or AyaNova can't find the language specified in the database then AyaNova defaults to English locale "en". +If no language is specified or AyaNova can't find the language specified in the database then AyaNova defaults to English translation "en". ## Built in language values @@ -17,7 +17,7 @@ You can use the ISO two letter country code or the English name of the language Valid settings: -| LANGUAGE | VALID SETTINGS | +| TRANSLATION | VALID SETTINGS | | ----- | ------------------------------ | | English | "en", "English" | | French | "fr", "French", "Français" | @@ -26,31 +26,31 @@ Valid settings: ## Custom language values -AyaNova allows for customized languages and this setting should be the exact name of a custom locale that exists within AyaNova if not using a built in language. +AyaNova allows for customized languages and this setting should be the exact name of a custom translation that exists within AyaNova if not using a built in language. ## Setting AyaNova expects the language setting to be provided by an environment variable or command line parameter named -`AYANOVA_DEFAULT_LANGUAGE` +`AYANOVA_DEFAULT_TRANSLATION` -The value specified should be a string containing one of the stock valid settings in the table above or the name of a custom locale, for example: +The value specified should be a string containing one of the stock valid settings in the table above or the name of a custom translation, for example: `French` or -`AcmeWidgetsCustomLocale` +`AcmeWidgetsCustomTranslation` Example command line parameter -`dotnet run --AYANOVA_DEFAULT_LANGUAGE="ES"` +`dotnet run --AYANOVA_DEFAULT_TRANSLATION="ES"` Example environment variable Windows -`set "AYANOVA_DEFAULT_LANGUAGE=DE"` +`set "AYANOVA_DEFAULT_TRANSLATION=DE"` Linux / MAC -`export AYANOVA_DEFAULT_LANGUAGE="MyCustomLocale"` +`export AYANOVA_DEFAULT_TRANSLATION="MyCustomTranslation"` If both a command line parameter and an environment variable are set the command line parameter takes precedence. diff --git a/docs/8.0/ayanova/docs/ops-config-environment-variables.md b/docs/8.0/ayanova/docs/ops-config-environment-variables.md index 4853a3ab..46b2669e 100644 --- a/docs/8.0/ayanova/docs/ops-config-environment-variables.md +++ b/docs/8.0/ayanova/docs/ops-config-environment-variables.md @@ -19,9 +19,9 @@ These values can all be specified as an environment variable or as a command lin - [AYANOVA_LOG_LEVEL](common-log.md#log-level) - [AYANOVA_LOG_PATH](common-log.md#log-path) -## LANGUAGE / LOCALE +## TRANSLATION -- [AYANOVA_DEFAULT_LANGUAGE](ops-config-default-language.md) +- [AYANOVA_DEFAULT_TRANSLATION](ops-config-default-translation.md) ## API diff --git a/docs/8.0/ayanova/docs/ops-error-codes.md b/docs/8.0/ayanova/docs/ops-error-codes.md index 89992c60..fe76de23 100644 --- a/docs/8.0/ayanova/docs/ops-error-codes.md +++ b/docs/8.0/ayanova/docs/ops-error-codes.md @@ -17,7 +17,7 @@ Here are all the error codes that can be returned by the AyaNova server: | E1010 | Could not find wwwRoot folder. AyaNova must be started from the folder immediately above wwwRoot. Generally the start folder should be the same folder as AyaNova.dll file. | | E1012 | Missing resource folder. AyaNova was started from the wrong location or the resource folder was not installed properly. This is required to intialize a new AyaNova database | | E1013 | Missing language resource file was deleted, renamed or not installed correctly. Resource language files are required to load into a new AyaNova database to display text in several languages for the user interface | -| E1015 | Missing language. One or more of the stock languages were not found in the database or a custom language specified in the config setting [AYANOVA_DEFAULT_LANGUAGE](ops-config-default-language.md) is missing from the database. Log will have details. | +| E1015 | Missing language. One or more of the stock languages were not found in the database or a custom language specified in the config setting [AYANOVA_DEFAULT_TRANSLATION](ops-config-default-language.md) is missing from the database. Log will have details. | | E1020 | Licensing related error. The message will contain the explanation | | E1030 | AyaNova database failed an integrity check. Contact support immediately. | | E1040 | File location [environment variables](ops-config-environment-variables.md) for backup files and user files were found to be the same location and must not be | diff --git a/docs/8.0/ayanova/mkdocs.yml b/docs/8.0/ayanova/mkdocs.yml index eea539fd..bdb2dcc7 100644 --- a/docs/8.0/ayanova/mkdocs.yml +++ b/docs/8.0/ayanova/mkdocs.yml @@ -26,7 +26,7 @@ nav: - 'Memos': 'form-home-memos.md' - 'Reminders': 'form-home-reminders.md' - 'User settings': 'form-home-user-settings.md' - - 'Locale': 'form-home-locale.md' + - 'Translation': 'form-home-translation.md' - 'Set password': 'form-home-password.md' - 'Notification subscriptions': 'form-home-notify-subscriptions.md' - Customers: @@ -58,7 +58,7 @@ nav: - 'Global settings': 'form-adm-global-settings.md' - 'License': 'form-adm-license.md' - 'Users': 'form-adm-users.md' - - 'Localized text design': 'form-adm-localized-text.md' + - 'Translation': 'form-adm-translation.md' - 'Report templates': 'form-adm-report-templates.md' - 'Attached files': 'form-adm-attachments.md' - 'History': 'form-adm-history.md' @@ -78,7 +78,7 @@ nav: - 'Customer service requests': 'form-customer-csr-list.md' - 'Widget (testing)': 'form-widget.md' - Features: - - 'Locale': 'ay-locale.md' + - 'Translation': 'ay-translation.md' - 'Notification': 'ay-notification.md' - Server operations guide: - Forms: @@ -92,7 +92,7 @@ nav: - Technical: - 'Installation': '_placeholder.md' - 'Logging': 'common-log.md' - - 'Language / locale': 'ops-config-default-language.md' + - 'Language / translation': 'ops-config-default-language.md' - 'Backup files folder': 'ops-config-folder-backup-files.md' - 'User files folder': 'ops-config-folder-user-files.md' - 'Database configuration': 'ops-config-db.md' diff --git a/linecounts/linecount.txt b/linecounts/linecount.txt index d3bf8a1b..9725959b 100644 --- a/linecounts/linecount.txt +++ b/linecounts/linecount.txt @@ -993,7 +993,7 @@ app\ayanova\README.md, code is 29, comment is 0, blank is 7. app\ayanova\src\api\apimeta.js, code is 16, comment is 2, blank is 1. app\ayanova\src\api\apiutil.js, code is 128, comment is 6, blank is 7. app\ayanova\src\api\auth.js, code is 26, comment is 2, blank is 1. -app\ayanova\src\api\locale.js, code is 37, comment is 5, blank is 1. +app\ayanova\src\api\translation.js, code is 37, comment is 5, blank is 1. app\ayanova\src\api\pagedlist.js, code is 17, comment is 9, blank is 3. app\ayanova\src\App.vue, code is 91, comment is 2, blank is 3. app\ayanova\src\assets\bw-logo.svg, code is 1, comment is 0, blank is 0. diff --git a/server/AyaNova/ControllerHelpers/UserLocaleIdFromContext.cs b/server/AyaNova/ControllerHelpers/UserTranslationIdFromContext.cs similarity index 64% rename from server/AyaNova/ControllerHelpers/UserLocaleIdFromContext.cs rename to server/AyaNova/ControllerHelpers/UserTranslationIdFromContext.cs index 9c6f1f89..7e6eaab6 100644 --- a/server/AyaNova/ControllerHelpers/UserLocaleIdFromContext.cs +++ b/server/AyaNova/ControllerHelpers/UserTranslationIdFromContext.cs @@ -2,13 +2,13 @@ using System.Collections.Generic; namespace AyaNova.Api.ControllerHelpers { - internal static class UserLocaleIdFromContext + internal static class UserTranslationIdFromContext { internal static long Id(IDictionary HttpContextItems) { - long? l = (long?)HttpContextItems["AY_LOCALE_ID"]; + long? l = (long?)HttpContextItems["AY_TRANSLATION_ID"]; if (l == null) - return AyaNova.Util.ServerBootConfig.AYANOVA_DEFAULT_LANGUAGE_ID; + return AyaNova.Util.ServerBootConfig.AYANOVA_DEFAULT_TRANSLATION_ID; return (long)l; } } diff --git a/server/AyaNova/Controllers/ApiRootController.cs b/server/AyaNova/Controllers/ApiRootController.cs index 3b15bc24..36f4aeca 100644 --- a/server/AyaNova/Controllers/ApiRootController.cs +++ b/server/AyaNova/Controllers/ApiRootController.cs @@ -63,7 +63,7 @@ namespace AyaNova.Api.Controllers AyaNova manual

API explorer

Email AyaNova support

-

{await LocaleBiz.GetDefaultLocalizedTextAsync("HelpLicense")}

+

{await TranslationBiz.GetDefaultLocalizedTextAsync("HelpLicense")}

{AyaNova.Core.License.LicenseInfo}

Schema version

{AySchema.currentSchema.ToString()}
diff --git a/server/AyaNova/Controllers/AttachmentController.cs b/server/AyaNova/Controllers/AttachmentController.cs index f794e2d6..a3f717f7 100644 --- a/server/AyaNova/Controllers/AttachmentController.cs +++ b/server/AyaNova/Controllers/AttachmentController.cs @@ -232,9 +232,8 @@ namespace AyaNova.Api.Controllers //EVENT LOG await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, attachToObject.ObjectId, attachToObject.ObjectType, AyaEvent.AttachmentCreate, v.DisplayFileName), ct); - //SEARCH INDEXING - // Search.ProcessNewObjectKeywords( UserLocaleIdFromContext.Id(HttpContext.Items), v.Id, AyaType.FileAttachment, v.DisplayFileName, v.DisplayFileName, v.Notes, v.StoredFileName); - var SearchParams = new Search.SearchIndexProcessObjectParameters(UserLocaleIdFromContext.Id(HttpContext.Items), v.Id, AyaType.FileAttachment, v.DisplayFileName); + //SEARCH INDEXING + var SearchParams = new Search.SearchIndexProcessObjectParameters(UserTranslationIdFromContext.Id(HttpContext.Items), v.Id, AyaType.FileAttachment, v.DisplayFileName); SearchParams.AddText(v.Notes).AddText(v.DisplayFileName).AddText(v.StoredFileName); await Search.ProcessNewObjectKeywordsAsync(SearchParams); diff --git a/server/AyaNova/Controllers/EnumPickListController.cs b/server/AyaNova/Controllers/EnumPickListController.cs index 9acd98cb..13444b65 100644 --- a/server/AyaNova/Controllers/EnumPickListController.cs +++ b/server/AyaNova/Controllers/EnumPickListController.cs @@ -55,8 +55,8 @@ namespace AyaNova.Api.Controllers return StatusCode(503, new ApiErrorResponse(ApiErrorCode.API_CLOSED, null, serverState.Reason)); } - long LocaleId = UserLocaleIdFromContext.Id(HttpContext.Items); - List LocaleKeysToFetch = new List(); + long TranslationId = UserTranslationIdFromContext.Id(HttpContext.Items); + List TranslationKeysToFetch = new List(); List ReturnList = new List(); @@ -90,14 +90,14 @@ namespace AyaNova.Api.Controllers } else if (keyNameInLowerCase == StringUtil.TrimTypeName(typeof(UserType).ToString()).ToLowerInvariant()) { - LocaleKeysToFetch.Add("UserTypesAdministrator"); - LocaleKeysToFetch.Add("UserTypesSchedulable"); - LocaleKeysToFetch.Add("UserTypesNonSchedulable"); - LocaleKeysToFetch.Add("UserTypesClient"); - LocaleKeysToFetch.Add("UserTypesHeadOffice"); - LocaleKeysToFetch.Add("UserTypesSubContractor"); - LocaleKeysToFetch.Add("UserTypesUtility"); - var LT = LocaleBiz.GetSubsetStaticAsync(LocaleKeysToFetch, LocaleId).Result; + TranslationKeysToFetch.Add("UserTypesAdministrator"); + TranslationKeysToFetch.Add("UserTypesSchedulable"); + TranslationKeysToFetch.Add("UserTypesNonSchedulable"); + TranslationKeysToFetch.Add("UserTypesClient"); + TranslationKeysToFetch.Add("UserTypesHeadOffice"); + TranslationKeysToFetch.Add("UserTypesSubContractor"); + TranslationKeysToFetch.Add("UserTypesUtility"); + var LT = TranslationBiz.GetSubsetStaticAsync(TranslationKeysToFetch, TranslationId).Result; ReturnList.Add(new NameIdItem() { Name = LT["UserTypesAdministrator"], Id = (long)UserType.Administrator }); ReturnList.Add(new NameIdItem() { Name = LT["UserTypesSchedulable"], Id = (long)UserType.Schedulable }); @@ -110,26 +110,26 @@ namespace AyaNova.Api.Controllers else if (keyNameInLowerCase == StringUtil.TrimTypeName(typeof(AuthorizationRoles).ToString()).ToLowerInvariant()) { - LocaleKeysToFetch.Add("AuthorizationRoleNoRole"); - LocaleKeysToFetch.Add("AuthorizationRoleBizAdminLimited"); - LocaleKeysToFetch.Add("AuthorizationRoleBizAdminFull"); - LocaleKeysToFetch.Add("AuthorizationRoleDispatchLimited"); - LocaleKeysToFetch.Add("AuthorizationRoleDispatchFull"); - LocaleKeysToFetch.Add("AuthorizationRoleInventoryLimited"); - LocaleKeysToFetch.Add("AuthorizationRoleInventoryFull"); - LocaleKeysToFetch.Add("AuthorizationRoleAccountingFull"); - LocaleKeysToFetch.Add("AuthorizationRoleTechLimited"); - LocaleKeysToFetch.Add("AuthorizationRoleTechFull"); - LocaleKeysToFetch.Add("AuthorizationRoleSubContractorLimited"); - LocaleKeysToFetch.Add("AuthorizationRoleSubContractorFull"); - LocaleKeysToFetch.Add("AuthorizationRoleCustomerLimited"); - LocaleKeysToFetch.Add("AuthorizationRoleCustomerFull"); - LocaleKeysToFetch.Add("AuthorizationRoleOpsAdminLimited"); - LocaleKeysToFetch.Add("AuthorizationRoleOpsAdminFull"); - LocaleKeysToFetch.Add("AuthorizationRoleSalesLimited"); - LocaleKeysToFetch.Add("AuthorizationRoleSalesFull"); - LocaleKeysToFetch.Add("AuthorizationRoleAll"); - var LT = LocaleBiz.GetSubsetStaticAsync(LocaleKeysToFetch, LocaleId).Result; + TranslationKeysToFetch.Add("AuthorizationRoleNoRole"); + TranslationKeysToFetch.Add("AuthorizationRoleBizAdminLimited"); + TranslationKeysToFetch.Add("AuthorizationRoleBizAdminFull"); + TranslationKeysToFetch.Add("AuthorizationRoleDispatchLimited"); + TranslationKeysToFetch.Add("AuthorizationRoleDispatchFull"); + TranslationKeysToFetch.Add("AuthorizationRoleInventoryLimited"); + TranslationKeysToFetch.Add("AuthorizationRoleInventoryFull"); + TranslationKeysToFetch.Add("AuthorizationRoleAccountingFull"); + TranslationKeysToFetch.Add("AuthorizationRoleTechLimited"); + TranslationKeysToFetch.Add("AuthorizationRoleTechFull"); + TranslationKeysToFetch.Add("AuthorizationRoleSubContractorLimited"); + TranslationKeysToFetch.Add("AuthorizationRoleSubContractorFull"); + TranslationKeysToFetch.Add("AuthorizationRoleCustomerLimited"); + TranslationKeysToFetch.Add("AuthorizationRoleCustomerFull"); + TranslationKeysToFetch.Add("AuthorizationRoleOpsAdminLimited"); + TranslationKeysToFetch.Add("AuthorizationRoleOpsAdminFull"); + TranslationKeysToFetch.Add("AuthorizationRoleSalesLimited"); + TranslationKeysToFetch.Add("AuthorizationRoleSalesFull"); + TranslationKeysToFetch.Add("AuthorizationRoleAll"); + var LT = TranslationBiz.GetSubsetStaticAsync(TranslationKeysToFetch, TranslationId).Result; ReturnList.Add(new NameIdItem() { Name = LT["AuthorizationRoleNoRole"], Id = (long)AuthorizationRoles.NoRole }); ReturnList.Add(new NameIdItem() { Name = LT["AuthorizationRoleBizAdminLimited"], Id = (long)AuthorizationRoles.BizAdminLimited }); diff --git a/server/AyaNova/Controllers/SearchController.cs b/server/AyaNova/Controllers/SearchController.cs index 621e9f1c..958d46bd 100644 --- a/server/AyaNova/Controllers/SearchController.cs +++ b/server/AyaNova/Controllers/SearchController.cs @@ -66,7 +66,7 @@ namespace AyaNova.Api.Controllers } //Do the search - var SearchResults = await Search.DoSearchAsync(ct, UserLocaleIdFromContext.Id(HttpContext.Items), UserRolesFromContext.Roles(HttpContext.Items), searchParams); + var SearchResults = await Search.DoSearchAsync(ct, UserTranslationIdFromContext.Id(HttpContext.Items), UserRolesFromContext.Roles(HttpContext.Items), searchParams); return Ok(ApiOkResponse.Response(SearchResults, true)); } diff --git a/server/AyaNova/Controllers/LocaleController.cs b/server/AyaNova/Controllers/TranslationController.cs similarity index 65% rename from server/AyaNova/Controllers/LocaleController.cs rename to server/AyaNova/Controllers/TranslationController.cs index e77f1704..20856054 100644 --- a/server/AyaNova/Controllers/LocaleController.cs +++ b/server/AyaNova/Controllers/TranslationController.cs @@ -28,10 +28,10 @@ namespace AyaNova.Api.Controllers [Route("api/v{version:apiVersion}/[controller]")] [Produces("application/json")] [Authorize] - public class LocaleController : ControllerBase + public class TranslationController : ControllerBase { private readonly AyContext ct; - private readonly ILogger log; + private readonly ILogger log; private readonly ApiServerState serverState; @@ -41,7 +41,7 @@ namespace AyaNova.Api.Controllers /// /// /// - public LocaleController(AyContext dbcontext, ILogger logger, ApiServerState apiServerState) + public TranslationController(AyContext dbcontext, ILogger logger, ApiServerState apiServerState) { ct = dbcontext; log = logger; @@ -52,12 +52,12 @@ namespace AyaNova.Api.Controllers /// - /// Get Locale all values + /// Get Translation all values /// /// - /// A single Locale and it's values + /// A single Translation and it's values [HttpGet("{id}")] - public async Task GetLocale([FromRoute] long id) + public async Task GetTranslation([FromRoute] long id) { if (serverState.IsClosed) { @@ -70,9 +70,8 @@ namespace AyaNova.Api.Controllers return BadRequest(new ApiErrorResponse(ModelState)); } - //Instantiate the business object handler - // LocaleBiz biz = new LocaleBiz(ct, UserIdFromContext.Id(HttpContext.Items), UserRolesFromContext.Roles(HttpContext.Items)); - LocaleBiz biz = LocaleBiz.GetBiz(ct, HttpContext); + //Instantiate the business object handler + TranslationBiz biz = TranslationBiz.GetBiz(ct, HttpContext); var o = await biz.GetAsync(id); @@ -87,11 +86,11 @@ namespace AyaNova.Api.Controllers /// - /// Get Locale pick list + /// Get Translation pick list /// - /// Picklist in alphabetical order of all locales + /// Picklist in alphabetical order of all Translations [HttpGet("PickList")] - public async Task LocalePickList() + public async Task TranslationPickList() { if (serverState.IsClosed) { @@ -99,8 +98,7 @@ namespace AyaNova.Api.Controllers } //Instantiate the business object handler - //LocaleBiz biz = new LocaleBiz(ct, UserIdFromContext.Id(HttpContext.Items), UserRolesFromContext.Roles(HttpContext.Items)); - LocaleBiz biz = LocaleBiz.GetBiz(ct, HttpContext); + TranslationBiz biz = TranslationBiz.GetBiz(ct, HttpContext); var l = await biz.GetPickListAsync(); return Ok(ApiOkResponse.Response(l, true)); @@ -109,11 +107,11 @@ namespace AyaNova.Api.Controllers #if (DEBUG) /// - /// Get a coverage report of locale keys used versus unused + /// Get a coverage report of translation keys used versus unused /// - /// Report of all unique locale keys requested since last server reboot - [HttpGet("LocaleKeyCoverage")] - public async Task LocaleKeyCoverage() + /// Report of all unique translation keys requested since last server reboot + [HttpGet("TranslationKeyCoverage")] + public async Task TranslationKeyCoverage() { if (serverState.IsClosed) { @@ -121,19 +119,18 @@ namespace AyaNova.Api.Controllers } //Instantiate the business object handler - LocaleBiz biz = LocaleBiz.GetBiz(ct, HttpContext); - //LocaleBiz biz = new LocaleBiz(ct, UserIdFromContext.Id(HttpContext.Items), UserRolesFromContext.Roles(HttpContext.Items)); - - var l = await biz.LocaleKeyCoverageAsync(); + TranslationBiz biz = TranslationBiz.GetBiz(ct, HttpContext); + + var l = await biz.TranslationKeyCoverageAsync(); return Ok(ApiOkResponse.Response(l, true)); } #endif /// - /// Get subset of locale values + /// Get subset of translation values /// - /// List of locale key strings + /// List of translation key strings /// A key value array of localized text values [HttpPost("SubSet")] public async Task SubSet([FromBody] List inObj) @@ -144,10 +141,9 @@ namespace AyaNova.Api.Controllers } //Instantiate the business object handler - //LocaleBiz biz = new LocaleBiz(ct, UserIdFromContext.Id(HttpContext.Items), UserRolesFromContext.Roles(HttpContext.Items)); - + //Instantiate the business object handler - LocaleBiz biz = LocaleBiz.GetBiz(ct, HttpContext); + TranslationBiz biz = TranslationBiz.GetBiz(ct, HttpContext); var l = await biz.GetSubsetAsync(inObj); return Ok(ApiOkResponse.Response(l, true)); @@ -155,11 +151,11 @@ namespace AyaNova.Api.Controllers /// - /// Duplicates an existing locale with a new name + /// Duplicates an existing translation with a new name /// - /// NameIdItem object containing source locale Id and new name + /// NameIdItem object containing source translation Id and new name /// Automatically filled from route path, no need to specify in body - /// Error response or newly created locale + /// Error response or newly created translation [HttpPost("Duplicate")] public async Task Duplicate([FromBody] NameIdItem inObj, ApiVersion apiVersion) { @@ -169,8 +165,7 @@ namespace AyaNova.Api.Controllers } //Instantiate the business object handler - // LocaleBiz biz = new LocaleBiz(ct, UserIdFromContext.Id(HttpContext.Items), UserRolesFromContext.Roles(HttpContext.Items)); - LocaleBiz biz = LocaleBiz.GetBiz(ct, HttpContext); + TranslationBiz biz = TranslationBiz.GetBiz(ct, HttpContext); var o = await biz.DuplicateAsync(inObj); @@ -181,20 +176,20 @@ namespace AyaNova.Api.Controllers } else { - return CreatedAtAction(nameof(LocaleController.GetLocale), new { id = o.Id, version = apiVersion.ToString() }, new ApiCreatedResponse(o)); + return CreatedAtAction(nameof(TranslationController.GetTranslation), new { id = o.Id, version = apiVersion.ToString() }, new ApiCreatedResponse(o)); } } /// - /// Put (UpdateLocaleItemDisplayText) + /// Put (UpdateTranslationItemDisplayText) /// Update a single key with new display text /// - /// NewText/Id/Concurrency token object. NewText is new display text, Id is LocaleItem Id, concurrency token is required + /// NewText/Id/Concurrency token object. NewText is new display text, Id is TranslationItem Id, concurrency token is required /// - [HttpPut("UpdateLocaleItemDisplayText")] - public async Task PutLocalItemDisplayText([FromBody] NewTextIdConcurrencyTokenItem inObj) + [HttpPut("UpdateTranslationItemDisplayText")] + public async Task PutTranslationItemDisplayText([FromBody] NewTextIdConcurrencyTokenItem inObj) { if (!serverState.IsOpen) { @@ -206,39 +201,38 @@ namespace AyaNova.Api.Controllers return BadRequest(new ApiErrorResponse(ModelState)); } - var oFromDb = await ct.LocaleItem.SingleOrDefaultAsync(m => m.Id == inObj.Id); + var oFromDb = await ct.TranslationItem.SingleOrDefaultAsync(m => m.Id == inObj.Id); if (oFromDb == null) { return NotFound(new ApiErrorResponse(ApiErrorCode.NOT_FOUND)); } - //Now fetch locale for rights and to ensure not stock - var oDbParent = await ct.Locale.SingleOrDefaultAsync(x => x.Id == oFromDb.LocaleId); + //Now fetch translation for rights and to ensure not stock + var oDbParent = await ct.Translation.SingleOrDefaultAsync(x => x.Id == oFromDb.TranslationId); if (oDbParent == null) { return NotFound(new ApiErrorResponse(ApiErrorCode.NOT_FOUND)); } - if (!Authorized.HasModifyRole(HttpContext.Items, AyaType.Locale)) + if (!Authorized.HasModifyRole(HttpContext.Items, AyaType.Translation)) { return StatusCode(403, new ApiNotAuthorizedResponse()); } - //Instantiate the business object handler - // LocaleBiz biz = new LocaleBiz(ct, UserIdFromContext.Id(HttpContext.Items), UserRolesFromContext.Roles(HttpContext.Items)); - LocaleBiz biz = LocaleBiz.GetBiz(ct, HttpContext); + //Instantiate the business object handler + TranslationBiz biz = TranslationBiz.GetBiz(ct, HttpContext); try { - if (!await biz.PutLocaleItemDisplayTextAsync(oFromDb, inObj, oDbParent)) + if (!await biz.PutTranslationItemDisplayTextAsync(oFromDb, inObj, oDbParent)) { return BadRequest(new ApiErrorResponse(biz.Errors)); } } catch (DbUpdateConcurrencyException) { - if (!await biz.LocaleItemExistsAsync(inObj.Id)) + if (!await biz.TranslationItemExistsAsync(inObj.Id)) { return NotFound(new ApiErrorResponse(ApiErrorCode.NOT_FOUND)); } @@ -256,13 +250,13 @@ namespace AyaNova.Api.Controllers } /// - /// Put (UpdateLocaleName) - /// Update a locale to change the name (non-stock locales only) + /// Put (UpdateTranslationName) + /// Update a translation to change the name (non-stock Translations only) /// - /// NewText/Id/Concurrency token object. NewText is new locale name, Id is Locale Id, concurrency token is required + /// NewText/Id/Concurrency token object. NewText is new translation name, Id is Translation Id, concurrency token is required /// - [HttpPut("UpdateLocaleName")] - public async Task PutLocaleName([FromBody] NewTextIdConcurrencyTokenItem inObj) + [HttpPut("UpdateTranslationName")] + public async Task PutTranslationName([FromBody] NewTextIdConcurrencyTokenItem inObj) { if (!serverState.IsOpen) { @@ -274,7 +268,7 @@ namespace AyaNova.Api.Controllers return BadRequest(new ApiErrorResponse(ModelState)); } - var oFromDb = await ct.Locale.SingleOrDefaultAsync(m => m.Id == inObj.Id); + var oFromDb = await ct.Translation.SingleOrDefaultAsync(m => m.Id == inObj.Id); if (oFromDb == null) { @@ -282,18 +276,17 @@ namespace AyaNova.Api.Controllers } - if (!Authorized.HasModifyRole(HttpContext.Items, AyaType.Locale)) + if (!Authorized.HasModifyRole(HttpContext.Items, AyaType.Translation)) { return StatusCode(403, new ApiNotAuthorizedResponse()); } - //Instantiate the business object handler - //LocaleBiz biz = new LocaleBiz(ct, UserIdFromContext.Id(HttpContext.Items), UserRolesFromContext.Roles(HttpContext.Items)); - LocaleBiz biz = LocaleBiz.GetBiz(ct, HttpContext); + //Instantiate the business object handler + TranslationBiz biz = TranslationBiz.GetBiz(ct, HttpContext); try { - if (!await biz.PutLocaleNameAsync(oFromDb, inObj)) + if (!await biz.PutTranslationNameAsync(oFromDb, inObj)) { return BadRequest(new ApiErrorResponse(biz.Errors)); } @@ -301,7 +294,7 @@ namespace AyaNova.Api.Controllers } catch (DbUpdateConcurrencyException) { - if (!await biz.LocaleExistsAsync(inObj.Id)) + if (!await biz.TranslationExistsAsync(inObj.Id)) { return NotFound(new ApiErrorResponse(ApiErrorCode.NOT_FOUND)); } @@ -319,12 +312,12 @@ namespace AyaNova.Api.Controllers /// - /// Delete Locale + /// Delete Translation /// /// /// Ok [HttpDelete("{id}")] - public async Task DeleteLocale([FromRoute] long id) + public async Task DeleteTranslation([FromRoute] long id) { if (!serverState.IsOpen) @@ -338,22 +331,22 @@ namespace AyaNova.Api.Controllers } - //Fetch locale and it's children + //Fetch translation and it's children //(fetch here so can return proper REST responses on failing basic validity) - var dbObj = await ct.Locale.Include(x => x.LocaleItems).SingleOrDefaultAsync(m => m.Id == id); + var dbObj = await ct.Translation.Include(x => x.TranslationItems).SingleOrDefaultAsync(m => m.Id == id); if (dbObj == null) { return NotFound(new ApiErrorResponse(ApiErrorCode.NOT_FOUND)); } - if (!Authorized.HasDeleteRole(HttpContext.Items, AyaType.Locale)) + if (!Authorized.HasDeleteRole(HttpContext.Items, AyaType.Translation)) { return StatusCode(403, new ApiNotAuthorizedResponse()); } //Instantiate the business object handler - LocaleBiz biz = LocaleBiz.GetBiz(ct, HttpContext); + TranslationBiz biz = TranslationBiz.GetBiz(ct, HttpContext); if (!await biz.DeleteAsync(dbObj)) { return BadRequest(new ApiErrorResponse(biz.Errors)); @@ -364,14 +357,14 @@ namespace AyaNova.Api.Controllers #if (DEBUG) - public class LocaleCoverageInfo + public class TranslationCoverageInfo { public List RequestedKeys { get; set; } public int RequestedKeyCount { get; set; } public List NotRequestedKeys { get; set; } public int NotRequestedKeyCount { get; set; } - public LocaleCoverageInfo() + public TranslationCoverageInfo() { RequestedKeys = new List(); NotRequestedKeys = new List(); diff --git a/server/AyaNova/DataList/DataListSqlFilterCriteriaBuilder.cs b/server/AyaNova/DataList/DataListSqlFilterCriteriaBuilder.cs index 1f9d637f..c1eaee27 100644 --- a/server/AyaNova/DataList/DataListSqlFilterCriteriaBuilder.cs +++ b/server/AyaNova/DataList/DataListSqlFilterCriteriaBuilder.cs @@ -455,7 +455,7 @@ namespace AyaNova.DataList case UiFieldDataType.InternalId: case UiFieldDataType.Integer: //whole numbers, not only integer { - //case 1795 - it's numeric, convert to locale independant format + //case 1795 - it's numeric, convert to translation independant format //RAVEN NOTE: this code looks suspect to me, but I'll leave it in for now NumberFormatInfo nfi = System.Globalization.CultureInfo.CurrentCulture.NumberFormat; switch (DataType) diff --git a/server/AyaNova/Program.cs b/server/AyaNova/Program.cs index 49977685..2fbe349b 100644 --- a/server/AyaNova/Program.cs +++ b/server/AyaNova/Program.cs @@ -177,7 +177,7 @@ namespace AyaNova logger.Debug("BOOT: User - {0}", Environment.UserName); logger.Debug("BOOT: .Net Version - {0}", Environment.Version.ToString()); logger.Debug("BOOT: CPU count - {0}", Environment.ProcessorCount); - logger.Debug("BOOT: Default language - \"{0}\"", ServerBootConfig.AYANOVA_DEFAULT_LANGUAGE); + logger.Debug("BOOT: Default language - \"{0}\"", ServerBootConfig.AYANOVA_DEFAULT_TRANSLATION); #endregion diff --git a/server/AyaNova/Startup.cs b/server/AyaNova/Startup.cs index ae1fb731..49627173 100644 --- a/server/AyaNova/Startup.cs +++ b/server/AyaNova/Startup.cs @@ -368,12 +368,11 @@ namespace AyaNova var ct = context.RequestServices.GetService(); //get the user record - //var u = ct.User.AsNoTracking().Where(a => a.Id == userId).Select(m => new { roles = m.Roles, name = m.Name, id = m.Id, localeId = m.LocaleId }).First(); - var u = await ct.User.AsNoTracking().Where(a => a.Id == userId).Select(m => new { roles = m.Roles, name = m.Name, id = m.Id, localeId = m.LocaleId }).FirstAsync(); + var u = await ct.User.AsNoTracking().Where(a => a.Id == userId).Select(m => new { roles = m.Roles, name = m.Name, id = m.Id, translationId = m.TranslationId }).FirstAsync(); context.Request.HttpContext.Items["AY_ROLES"] = u.roles; context.Request.HttpContext.Items["AY_USERNAME"] = u.name; context.Request.HttpContext.Items["AY_USER_ID"] = u.id; - context.Request.HttpContext.Items["AY_LOCALE_ID"] = u.localeId; + context.Request.HttpContext.Items["AY_TRANSLATION_ID"] = u.translationId; } await next.Invoke(); }); @@ -443,9 +442,9 @@ namespace AyaNova //Initialize license AyaNova.Core.License.InitializeAsync(apiServerState, dbContext, _newLog).Wait(); - //Ensure locales are present, not missing any keys and that there is a server default locale that exists - LocaleBiz lb = new LocaleBiz(dbContext, 1, ServerBootConfig.AYANOVA_DEFAULT_LANGUAGE_ID, AuthorizationRoles.OpsAdminFull); - lb.ValidateLocalesAsync().Wait(); + //Ensure translations are present, not missing any keys and that there is a server default translation that exists + TranslationBiz lb = new TranslationBiz(dbContext, 1, ServerBootConfig.AYANOVA_DEFAULT_TRANSLATION_ID, AuthorizationRoles.OpsAdminFull); + lb.ValidateTranslationsAsync().Wait(); diff --git a/server/AyaNova/biz/AyaEvent.cs b/server/AyaNova/biz/AyaEvent.cs index 05ce08d6..48b4040d 100644 --- a/server/AyaNova/biz/AyaEvent.cs +++ b/server/AyaNova/biz/AyaEvent.cs @@ -23,7 +23,7 @@ namespace AyaNova.Biz ServerStateChange=9, SeedDatabase=10 - //NEW ITEMS REQUIRE LOCALE KEYS AND UPDATE EventLogProcessor code that prefetches required keys + //NEW ITEMS REQUIRE translation KEYS AND UPDATE EventLogProcessor code that prefetches required keys } diff --git a/server/AyaNova/biz/AyaType.cs b/server/AyaNova/biz/AyaType.cs index de320f6a..226d8e57 100644 --- a/server/AyaNova/biz/AyaType.cs +++ b/server/AyaNova/biz/AyaType.cs @@ -33,7 +33,7 @@ namespace AyaNova.Biz AyaNova7Import = 10, TrialSeeder = 11, Metrics = 12, - Locale = 13, + Translation = 13, UserOptions = 14, DEPRECATED_REUSELATER_15 = 15, DEPRECATED_REUSELATER_16 = 16, diff --git a/server/AyaNova/biz/BizObject.cs b/server/AyaNova/biz/BizObject.cs index dad07ed7..48b28f6d 100644 --- a/server/AyaNova/biz/BizObject.cs +++ b/server/AyaNova/biz/BizObject.cs @@ -28,7 +28,7 @@ namespace AyaNova.Biz internal AyaType BizType { get; set; } internal AyaNova.Models.AyContext ct { get; set; } internal long UserId { get; set; } - internal long UserLocaleId { get; set; } + internal long UserTranslationId { get; set; } internal AuthorizationRoles CurrentUserRoles { get; set; } #endregion diff --git a/server/AyaNova/biz/BizObjectFactory.cs b/server/AyaNova/biz/BizObjectFactory.cs index fdfe3046..6e86f435 100644 --- a/server/AyaNova/biz/BizObjectFactory.cs +++ b/server/AyaNova/biz/BizObjectFactory.cs @@ -24,22 +24,22 @@ namespace AyaNova.Biz switch (aytype) { case AyaType.User: - return new UserBiz(dbcontext, userId, ServerBootConfig.AYANOVA_DEFAULT_LANGUAGE_ID, roles); + return new UserBiz(dbcontext, userId, ServerBootConfig.AYANOVA_DEFAULT_TRANSLATION_ID, roles); case AyaType.Widget: - return new WidgetBiz(dbcontext, userId, ServerBootConfig.AYANOVA_DEFAULT_LANGUAGE_ID, roles); + return new WidgetBiz(dbcontext, userId, ServerBootConfig.AYANOVA_DEFAULT_TRANSLATION_ID, roles); case AyaType.JobOperations: return new JobOperationsBiz(dbcontext, userId, roles); case AyaType.AyaNova7Import: return new ImportAyaNova7Biz(dbcontext, userId, roles); case AyaType.TrialSeeder: return new TrialBiz(dbcontext, userId, roles); - case AyaType.Locale: - return new LocaleBiz(dbcontext, userId, ServerBootConfig.AYANOVA_DEFAULT_LANGUAGE_ID, roles); + case AyaType.Translation: + return new TranslationBiz(dbcontext, userId, ServerBootConfig.AYANOVA_DEFAULT_TRANSLATION_ID, roles); case AyaType.DataListView: - return new DataListViewBiz(dbcontext, userId, ServerBootConfig.AYANOVA_DEFAULT_LANGUAGE_ID, roles); + return new DataListViewBiz(dbcontext, userId, ServerBootConfig.AYANOVA_DEFAULT_TRANSLATION_ID, roles); case AyaType.FormCustom: - return new FormCustomBiz(dbcontext, userId, ServerBootConfig.AYANOVA_DEFAULT_LANGUAGE_ID, roles); + return new FormCustomBiz(dbcontext, userId, ServerBootConfig.AYANOVA_DEFAULT_TRANSLATION_ID, roles); default: diff --git a/server/AyaNova/biz/BizRoles.cs b/server/AyaNova/biz/BizRoles.cs index 74dafdc1..3def6788 100644 --- a/server/AyaNova/biz/BizRoles.cs +++ b/server/AyaNova/biz/BizRoles.cs @@ -121,9 +121,9 @@ namespace AyaNova.Biz //////////////////////////////////////////////////////////// - //LOCALE + //TRANSLATION // - roles.Add(AyaType.Locale, new BizRoleSet() + roles.Add(AyaType.Translation, new BizRoleSet() { Change = AuthorizationRoles.BizAdminFull | AuthorizationRoles.OpsAdminFull, //Anyone can read it because they need to to open a form, but also in UI @@ -174,8 +174,8 @@ namespace AyaNova.Biz // System.Diagnostics.Debugger.Log(1, "JSONFRAGMENTFORCLIENT", json); //ONGOING VALIDATION TO CATCH MISMATCH WHEN NEW ROLES ADDED (wont' catch changes to existing unfortunately) - //var lastRoles = "{\"User\":{\"Change\":2,\"ReadFullRecord\":1},\"UserOptions\":{\"Change\":2,\"ReadFullRecord\":1},\"Widget\":{\"Change\":34,\"ReadFullRecord\":17},\"ServerState\":{\"Change\":16384,\"ReadFullRecord\":32767},\"License\":{\"Change\":16386,\"ReadFullRecord\":8193},\"LogFile\":{\"Change\":0,\"ReadFullRecord\":24576},\"JobOperations\":{\"Change\":16384,\"ReadFullRecord\":8195},\"AyaNova7Import\":{\"Change\":16384,\"ReadFullRecord\":0},\"Metrics\":{\"Change\":0,\"ReadFullRecord\":24576},\"Locale\":{\"Change\":16386,\"ReadFullRecord\":32767},\"DataListFilter\":{\"Change\":2,\"ReadFullRecord\":32767},\"FormCustom\":{\"Change\":2,\"ReadFullRecord\":32767}}"; - var lastRoles = "{\"User\":{\"Change\":2,\"ReadFullRecord\":1},\"UserOptions\":{\"Change\":2,\"ReadFullRecord\":1},\"Widget\":{\"Change\":34,\"ReadFullRecord\":17},\"ServerState\":{\"Change\":16384,\"ReadFullRecord\":131071},\"License\":{\"Change\":16386,\"ReadFullRecord\":8193},\"LogFile\":{\"Change\":0,\"ReadFullRecord\":24576},\"JobOperations\":{\"Change\":16384,\"ReadFullRecord\":8195},\"AyaNova7Import\":{\"Change\":16384,\"ReadFullRecord\":0},\"Metrics\":{\"Change\":0,\"ReadFullRecord\":24576},\"Locale\":{\"Change\":16386,\"ReadFullRecord\":131071},\"DataListView\":{\"Change\":2,\"ReadFullRecord\":131071},\"FormCustom\":{\"Change\":2,\"ReadFullRecord\":131071}}"; + //var lastRoles = "{\"User\":{\"Change\":2,\"ReadFullRecord\":1},\"UserOptions\":{\"Change\":2,\"ReadFullRecord\":1},\"Widget\":{\"Change\":34,\"ReadFullRecord\":17},\"ServerState\":{\"Change\":16384,\"ReadFullRecord\":32767},\"License\":{\"Change\":16386,\"ReadFullRecord\":8193},\"LogFile\":{\"Change\":0,\"ReadFullRecord\":24576},\"JobOperations\":{\"Change\":16384,\"ReadFullRecord\":8195},\"AyaNova7Import\":{\"Change\":16384,\"ReadFullRecord\":0},\"Metrics\":{\"Change\":0,\"ReadFullRecord\":24576},\"Translation\":{\"Change\":16386,\"ReadFullRecord\":32767},\"DataListFilter\":{\"Change\":2,\"ReadFullRecord\":32767},\"FormCustom\":{\"Change\":2,\"ReadFullRecord\":32767}}"; + var lastRoles = "{\"User\":{\"Change\":2,\"ReadFullRecord\":1},\"UserOptions\":{\"Change\":2,\"ReadFullRecord\":1},\"Widget\":{\"Change\":34,\"ReadFullRecord\":17},\"ServerState\":{\"Change\":16384,\"ReadFullRecord\":131071},\"License\":{\"Change\":16386,\"ReadFullRecord\":8193},\"LogFile\":{\"Change\":0,\"ReadFullRecord\":24576},\"JobOperations\":{\"Change\":16384,\"ReadFullRecord\":8195},\"AyaNova7Import\":{\"Change\":16384,\"ReadFullRecord\":0},\"Metrics\":{\"Change\":0,\"ReadFullRecord\":24576},\"Translation\":{\"Change\":16386,\"ReadFullRecord\":131071},\"DataListView\":{\"Change\":2,\"ReadFullRecord\":131071},\"FormCustom\":{\"Change\":2,\"ReadFullRecord\":131071}}"; Dictionary lastRolesDeserialized = Newtonsoft.Json.JsonConvert.DeserializeObject>(lastRoles); if (lastRolesDeserialized.Count != roles.Count) { diff --git a/server/AyaNova/biz/DataListViewBiz.cs b/server/AyaNova/biz/DataListViewBiz.cs index 7699c3c1..9fce904b 100644 --- a/server/AyaNova/biz/DataListViewBiz.cs +++ b/server/AyaNova/biz/DataListViewBiz.cs @@ -16,11 +16,11 @@ namespace AyaNova.Biz internal class DataListViewBiz : BizObject { - internal DataListViewBiz(AyContext dbcontext, long currentUserId, long userLocaleId, AuthorizationRoles UserRoles) + internal DataListViewBiz(AyContext dbcontext, long currentUserId, long userTranslationId, AuthorizationRoles UserRoles) { ct = dbcontext; UserId = currentUserId; - UserLocaleId = userLocaleId; + UserTranslationId = userTranslationId; CurrentUserRoles = UserRoles; BizType = AyaType.DataListView; } @@ -28,9 +28,9 @@ namespace AyaNova.Biz internal static DataListViewBiz GetBiz(AyContext ct, Microsoft.AspNetCore.Http.HttpContext httpContext = null) { if (httpContext != null) - return new DataListViewBiz(ct, UserIdFromContext.Id(httpContext.Items), UserLocaleIdFromContext.Id(httpContext.Items), UserRolesFromContext.Roles(httpContext.Items)); + return new DataListViewBiz(ct, UserIdFromContext.Id(httpContext.Items), UserTranslationIdFromContext.Id(httpContext.Items), UserRolesFromContext.Roles(httpContext.Items)); else - return new DataListViewBiz(ct, 1, ServerBootConfig.AYANOVA_DEFAULT_LANGUAGE_ID, AuthorizationRoles.BizAdminFull); + return new DataListViewBiz(ct, 1, ServerBootConfig.AYANOVA_DEFAULT_TRANSLATION_ID, AuthorizationRoles.BizAdminFull); } @@ -66,8 +66,7 @@ namespace AyaNova.Biz //EVENT LOG await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, outObj.Id, BizType, AyaEvent.Created), ct); - //SEARCH INDEXING - // Search.ProcessNewObjectKeywords(UserLocaleId, outObj.Id, BizType, outObj.Name, outObj.Name); + return outObj; @@ -178,8 +177,7 @@ namespace AyaNova.Biz //Log modification and save context await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, dbObj.Id, BizType, AyaEvent.Modified), ct); - //Update keywords - // Search.ProcessUpdatedObjectKeywords(UserLocaleId, dbObj.Id, BizType, dbObj.Name, dbObj.Name); + return true; } diff --git a/server/AyaNova/biz/FormCustomBiz.cs b/server/AyaNova/biz/FormCustomBiz.cs index 59235bb1..85b08729 100644 --- a/server/AyaNova/biz/FormCustomBiz.cs +++ b/server/AyaNova/biz/FormCustomBiz.cs @@ -15,11 +15,11 @@ namespace AyaNova.Biz internal class FormCustomBiz : BizObject { - internal FormCustomBiz(AyContext dbcontext, long currentUserId, long userLocaleId, AuthorizationRoles UserRoles) + internal FormCustomBiz(AyContext dbcontext, long currentUserId, long userTranslationId, AuthorizationRoles UserRoles) { ct = dbcontext; UserId = currentUserId; - UserLocaleId = userLocaleId; + UserTranslationId = userTranslationId; CurrentUserRoles = UserRoles; BizType = AyaType.FormCustom; } @@ -27,9 +27,9 @@ namespace AyaNova.Biz internal static FormCustomBiz GetBiz(AyContext ct, Microsoft.AspNetCore.Http.HttpContext httpContext = null) { if (httpContext != null) - return new FormCustomBiz(ct, UserIdFromContext.Id(httpContext.Items), UserLocaleIdFromContext.Id(httpContext.Items), UserRolesFromContext.Roles(httpContext.Items)); + return new FormCustomBiz(ct, UserIdFromContext.Id(httpContext.Items), UserTranslationIdFromContext.Id(httpContext.Items), UserRolesFromContext.Roles(httpContext.Items)); else//when called internally for internal ops there will be no context so need to set default values for that - return new FormCustomBiz(ct, 1, ServerBootConfig.AYANOVA_DEFAULT_LANGUAGE_ID, AuthorizationRoles.BizAdminFull); + return new FormCustomBiz(ct, 1, ServerBootConfig.AYANOVA_DEFAULT_TRANSLATION_ID, AuthorizationRoles.BizAdminFull); } @@ -65,9 +65,7 @@ namespace AyaNova.Biz //EVENT LOG await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, outObj.Id, BizType, AyaEvent.Created), ct); - //SEARCH INDEXING - // Search.ProcessNewObjectKeywords(UserLocaleId, outObj.Id, BizType, outObj.Name, outObj.Name); - + return outObj; } @@ -136,9 +134,7 @@ namespace AyaNova.Biz //Log modification and save context await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, dbObj.Id, BizType, AyaEvent.Modified), ct); - //Update keywords - // Search.ProcessUpdatedObjectKeywords(UserLocaleId, dbObj.Id, BizType, dbObj.Name, dbObj.Name); - + return true; } diff --git a/server/AyaNova/biz/ImportAyaNova7Biz.cs b/server/AyaNova/biz/ImportAyaNova7Biz.cs index 945f0e2a..46b6c668 100644 --- a/server/AyaNova/biz/ImportAyaNova7Biz.cs +++ b/server/AyaNova/biz/ImportAyaNova7Biz.cs @@ -155,10 +155,10 @@ namespace AyaNova.Biz - //IMPORT LOCALES - await DoImportAsync("GZTW.AyaNova.BLL.Locale", "main", AyaType.Locale, job.GId, importMap, importFileName, zipEntries, TagLists); - //Now can do user locale settings properly - await DoImportAsync("GZTW.AyaNova.BLL.User", "locale", AyaType.User, job.GId, importMap, importFileName, zipEntries, TagLists); + //IMPORT TRANSLATIONS + await DoImportAsync("GZTW.AyaNova.BLL.Translation", "main", AyaType.Translation, job.GId, importMap, importFileName, zipEntries, TagLists); + //Now can do user translation settings properly + await DoImportAsync("GZTW.AyaNova.BLL.User", "translation", AyaType.User, job.GId, importMap, importFileName, zipEntries, TagLists); //TODO: CLIENT //do import for client here diff --git a/server/AyaNova/biz/PrimeData.cs b/server/AyaNova/biz/PrimeData.cs index 511bd73b..2512c29c 100644 --- a/server/AyaNova/biz/PrimeData.cs +++ b/server/AyaNova/biz/PrimeData.cs @@ -9,7 +9,7 @@ using AyaNova.Models; namespace AyaNova.Biz { - //Prime the database with initial, minimum required data to boot and do things (manager account, locales) + //Prime the database with initial, minimum required data to boot and do things (manager account, translations) public static class PrimeData { @@ -28,7 +28,7 @@ namespace AyaNova.Biz u.Password = Hasher.hash(u.Salt, "l3tm3in"); u.Roles = AuthorizationRoles.All;//AuthorizationRoles.BizAdminFull | AuthorizationRoles.OpsAdminFull | AuthorizationRoles.DispatchFull | AuthorizationRoles.InventoryFull; - u.LocaleId = ServerBootConfig.AYANOVA_DEFAULT_LANGUAGE_ID;//Ensure primeLocales is called first + u.TranslationId = ServerBootConfig.AYANOVA_DEFAULT_TRANSLATION_ID;//Ensure primeTranslations is called first u.UserType = UserType.Administrator; u.UserOptions = new UserOptions(); await ct.User.AddAsync(u); @@ -38,14 +38,14 @@ namespace AyaNova.Biz /// - /// Prime the locales + /// Prime the Translations /// This may be called before there are any users on a fresh db boot /// - public static async Task PrimeLocales() + public static async Task PrimeTranslations() {// - //Read in each stock locale from a text file and then create them in the DB + //Read in each stock translation from a text file and then create them in the DB var ResourceFolderPath = Path.Combine(ServerBootConfig.AYANOVA_CONTENT_ROOT_PATH, "resource"); if (!Directory.Exists(ResourceFolderPath)) { @@ -53,30 +53,30 @@ namespace AyaNova.Biz } - await ImportLocale(ResourceFolderPath, "en"); - await ImportLocale(ResourceFolderPath, "es"); - await ImportLocale(ResourceFolderPath, "fr"); - await ImportLocale(ResourceFolderPath, "de"); + await ImportTranslation(ResourceFolderPath, "en"); + await ImportTranslation(ResourceFolderPath, "es"); + await ImportTranslation(ResourceFolderPath, "fr"); + await ImportTranslation(ResourceFolderPath, "de"); - //Ensure locales are present, not missing any keys and that there is a server default locale that exists - LocaleBiz lb = LocaleBiz.GetBiz(ServiceProviderProvider.DBContext); - await lb.ValidateLocalesAsync(); + //Ensure Translations are present, not missing any keys and that there is a server default translation that exists + TranslationBiz lb = TranslationBiz.GetBiz(ServiceProviderProvider.DBContext); + await lb.ValidateTranslationsAsync(); } - private static async Task ImportLocale(string resourceFolderPath, string localeCode) + private static async Task ImportTranslation(string resourceFolderPath, string translationCode) { AyContext ct = ServiceProviderProvider.DBContext; - var LocalePath = Path.Combine(resourceFolderPath, $"{localeCode}.json"); - if (!File.Exists(LocalePath)) + var TranslationPath = Path.Combine(resourceFolderPath, $"{translationCode}.json"); + if (!File.Exists(TranslationPath)) { - throw new System.Exception($"E1013: stock locale file \"{localeCode}\" not found where expected: \"{LocalePath}\", installation damaged?"); + throw new System.Exception($"E1013: stock translation file \"{translationCode}\" not found where expected: \"{TranslationPath}\", installation damaged?"); } - JObject o = JObject.Parse(await File.ReadAllTextAsync(LocalePath)); + JObject o = JObject.Parse(await File.ReadAllTextAsync(TranslationPath)); - Locale l = new Locale(); - l.Name = localeCode; + Translation l = new Translation(); + l.Name = translationCode; l.Stock = true; l.CjkIndex = false; @@ -85,10 +85,10 @@ namespace AyaNova.Biz { var key = t.Path; var display = t.First.Value(); - l.LocaleItems.Add(new LocaleItem() { Key = key, Display = display });//, Locale = l + l.TranslationItems.Add(new TranslationItem() { Key = key, Display = display }); } - await ct.Locale.AddAsync(l); + await ct.Translation.AddAsync(l); await ct.SaveChangesAsync(); } diff --git a/server/AyaNova/biz/Search.cs b/server/AyaNova/biz/Search.cs index 11888c2a..24f583dd 100644 --- a/server/AyaNova/biz/Search.cs +++ b/server/AyaNova/biz/Search.cs @@ -107,7 +107,7 @@ namespace AyaNova.Biz } - public static async Task DoSearchAsync(AyContext ct, long localeId, AuthorizationRoles currentUserRoles, SearchRequestParameters searchParameters) + public static async Task DoSearchAsync(AyContext ct, long translationId, AuthorizationRoles currentUserRoles, SearchRequestParameters searchParameters) { var ReturnObject = new SearchReturnObject(); @@ -125,7 +125,7 @@ namespace AyaNova.Biz searchParameters.Phrase = searchParameters.Phrase.Replace("*", "%"); //BREAK SEARCH PHRASE INTO SEPARATE TERMS - var PhraseItems = await BreakSearchPhraseAsync(localeId, searchParameters.Phrase); + var PhraseItems = await BreakSearchPhraseAsync(translationId, searchParameters.Phrase); //SPLIT OUT WILDCARDS FROM NON WILDCARDS List WildCardSearchTerms = new List(); @@ -374,7 +374,7 @@ namespace AyaNova.Biz //Class to hold process input parameters public class SearchIndexProcessObjectParameters { - public long LocaleId { get; set; } + public long TranslationId { get; set; } public long ObjectId { get; set; } public AyaType ObjectType { get; set; } public string Name { get; set; } @@ -382,11 +382,11 @@ namespace AyaNova.Biz - public SearchIndexProcessObjectParameters(long localeId, long objectID, AyaType objectType, string name) + public SearchIndexProcessObjectParameters(long translationId, long objectID, AyaType objectType, string name) { Words = new List(); - LocaleId = localeId; + TranslationId = translationId; ObjectId = objectID; ObjectType = objectType; Name = name; @@ -436,14 +436,14 @@ namespace AyaNova.Biz } - public static async Task ProcessNewObjectKeywordsAsync(SearchIndexProcessObjectParameters searchIndexObjectParameters)//(long localeId, long objectID, AyaType objectType, string name, params string[] text) + public static async Task ProcessNewObjectKeywordsAsync(SearchIndexProcessObjectParameters searchIndexObjectParameters) { - await ProcessKeywordsAsync(searchIndexObjectParameters, true);//localeId, objectID, objectType, true, name, text); + await ProcessKeywordsAsync(searchIndexObjectParameters, true); } - public static async Task ProcessUpdatedObjectKeywordsAsync(SearchIndexProcessObjectParameters searchIndexObjectParameters)// localeId, long objectID, AyaType objectType, string name, params string[] text) + public static async Task ProcessUpdatedObjectKeywordsAsync(SearchIndexProcessObjectParameters searchIndexObjectParameters) { - await ProcessKeywordsAsync(searchIndexObjectParameters, false);//localeId, objectID, objectType, false, name, text); + await ProcessKeywordsAsync(searchIndexObjectParameters, false); } public static async Task ProcessDeletedObjectKeywordsAsync(long objectID, AyaType objectType) @@ -463,11 +463,11 @@ namespace AyaNova.Biz /// Process the keywords into the dictionary /// NOTE: NAME parameter is in ADDITION to the NAME also being one of the strings passed in text parameter /// - private static async Task ProcessKeywordsAsync(SearchIndexProcessObjectParameters p, bool newRecord)//long localeId, long objectID, AyaType objectType, string name, params string[] text) + private static async Task ProcessKeywordsAsync(SearchIndexProcessObjectParameters p, bool newRecord) { #if (DEBUG) - if (p.ObjectType == AyaType.JobOperations || p.ObjectType == AyaType.Locale) + if (p.ObjectType == AyaType.JobOperations || p.ObjectType == AyaType.Translation) { throw new System.NotSupportedException($"Search::ProcessKeywords - Invalid type presented {p.ObjectType}"); } @@ -481,10 +481,10 @@ namespace AyaNova.Biz } //BREAK OBJECT TEXT STRINGS INTO KEYWORD LIST - List KeyWordList = await BreakAsync(p.LocaleId, p.Words); + List KeyWordList = await BreakAsync(p.TranslationId, p.Words); //BREAK NAME STRING - List NameKeyWordList = await BreakAsync(p.LocaleId, p.Name); + List NameKeyWordList = await BreakAsync(p.TranslationId, p.Name); //EARLY EXIT IF NO KEYWORDS OR NAME RECORD OR TAGS TO PROCESS @@ -573,7 +573,7 @@ Async the keyword processing Removing use of EF entirely in search indexing processing in favor of direct sql queries -cache or provide directly the locale to save time repeatedly fetching it when doing bulk ops!!! +cache or provide directly the translation to save time repeatedly fetching it when doing bulk ops!!! -After doing this 500=21 That's as fast as when I stripped out all the text, what a huge overhead saving right there!: 2020-01-24 12:00:41.2547|INFO|Seeder|Seeding 500 Widgets.... 2020-01-24 12:00:51.9138|INFO|Seeder|500 Widgets seeded in 10649 ms @@ -692,27 +692,27 @@ cache or provide directly the locale to save time repeatedly fetching it when do #region Breaker - //Class to hold relevant locale data for breaking text - public class LocaleWordBreakingData + //Class to hold relevant translation data for breaking text + public class TranslationWordBreakingData { public bool CJKIndex { get; set; } public List StopWords { get; set; } - public LocaleWordBreakingData() + public TranslationWordBreakingData() { CJKIndex = false; StopWords = new List(); } } -private static Dictionary localeWordBreakingDataCache = new Dictionary(); +private static Dictionary translationWordBreakingDataCache = new Dictionary(); // //called at startup to populate cache //WAS GOING TO ADD THIS IN RESPONSE TO AN ISSUE WITH EXCEPTION ATTEMPTING TO ADD ALREADY EXISTING DICTIONARY ID 1, BUT IT NEVER HAPPENED AGAIN, SO :SHRUGEMOJI: //IF IT DOES, MAKE THIS CODE AND POPULATE IT AT SERVER BOOT AND SHOULD BE ADEQUATE //OR GO NUTS WITH A FULL MEMORY CACHE: https://docs.microsoft.com/en-us/aspnet/core/performance/caching/memory?view=aspnetcore-3.1 -// internal static async Task CacheAllLocaleWordBreakingData(){ -// //iterate all locales, cache the word break data -// l = await ct.Locale +// internal static async Task CacheAllTranslationWordBreakingData(){ +// //iterate all Translations, cache the word break data +// l = await ct.Translation // .AsNoTracking() // .OrderBy(m => m.Name) // .Select(m => new NameIdItem() @@ -720,17 +720,17 @@ private static Dictionary localeWordBreakingDataCa // Id = m.Id, // Name = m.Name // }).ToListAsync(); -// localeWordBreakingDataCache.Add(localeId, await GetLocaleSearchDataAsync(localeId)); +// TranslationWordBreakingDataCache.Add(TranslationId, await GetTranslationSearchDataAsync(TranslationId)); // } - internal static async Task GetLocaleSearchDataAsync(long localeId, AyContext ct = null) + internal static async Task GetTranslationSearchDataAsync(long translationId, AyContext ct = null) { - LocaleWordBreakingData LSD = new LocaleWordBreakingData(); + TranslationWordBreakingData LSD = new TranslationWordBreakingData(); if (ct == null) ct = ServiceProviderProvider.DBContext; //Get stopwords - //Validate locale id, if not right then use default instead + //Validate translation id, if not right then use default instead var Param = new List(); - localeId = await LocaleBiz.ReturnSpecifiedLocaleIdIfExistsOrDefaultLocaleId(localeId, ct); + translationId = await TranslationBiz.ReturnSpecifiedTranslationIdIfExistsOrDefaultTranslationId(translationId, ct); Param.Add("StopWords1"); Param.Add("StopWords2"); Param.Add("StopWords3"); @@ -738,18 +738,18 @@ private static Dictionary localeWordBreakingDataCa Param.Add("StopWords5"); Param.Add("StopWords6"); Param.Add("StopWords7"); - var Stops = await LocaleBiz.GetSubsetStaticAsync(Param, localeId); + var Stops = await TranslationBiz.GetSubsetStaticAsync(Param, translationId); foreach (KeyValuePair kvp in Stops) { - //Each stopwords locale key is a space delimited list of words and in the case of an empty local string (i.e. StopWords7) it's value is a single question mark + //Each stopwords translation key is a space delimited list of words and in the case of an empty local string (i.e. StopWords7) it's value is a single question mark if (kvp.Value != "?") { LSD.StopWords.AddRange(kvp.Value.Split(" ")); } } - LSD.CJKIndex = await LocaleBiz.GetCJKIndexAsync(localeId, ct); + LSD.CJKIndex = await TranslationBiz.GetCJKIndexAsync(translationId, ct); return LSD; } @@ -763,34 +763,34 @@ private static Dictionary localeWordBreakingDataCa /// keywords suitable for passing to a /// stored procedure or other function /// - /// Use Locale setting CJKIndex=true to handle Chinese, Japanese, Korean etc + /// Use Translation setting CJKIndex=true to handle Chinese, Japanese, Korean etc /// (languages with no easily identifiable word boundaries as in english) /// /// List of strings - internal static async Task> BreakAsync(long localeId, List textStrings) + internal static async Task> BreakAsync(long translationId, List textStrings) { - return await BreakCoreAsync(localeId, false, textStrings); + return await BreakCoreAsync(translationId, false, textStrings); } /// /// /// - internal static async Task> BreakAsync(long localeId, string textString) + internal static async Task> BreakAsync(long translationId, string textString) { List textStrings = new List(1); textStrings.Add(textString); - return await BreakCoreAsync(localeId, false, textStrings); + return await BreakCoreAsync(translationId, false, textStrings); } /// /// Used to Process users search phrase and preserve wild /// cards entered /// - internal static async Task> BreakSearchPhraseAsync(long localeId, string searchPhrase) + internal static async Task> BreakSearchPhraseAsync(long translationId, string searchPhrase) { List textStrings = new List(); textStrings.Add(searchPhrase); - return await BreakCoreAsync(localeId, true, textStrings); + return await BreakCoreAsync(translationId, true, textStrings); } /// @@ -798,24 +798,17 @@ private static Dictionary localeWordBreakingDataCa /// used for eliminating noise words from search dictionary /// - - // //called by Locale in the rare circumstance that a locale has changed that is cached - // //and might affect word breaking (stopwords cjkindex etc) - // internal static void ClearLocaleWordBreakingDataCache(long localeId) - // { - // localeWordBreakingDataCache.Remove(localeId); - // } - internal static async Task> BreakCoreAsync(long localeId, bool KeepWildCards, List textStrings) + internal static async Task> BreakCoreAsync(long translationId, bool KeepWildCards, List textStrings) { //For stopwords and CJKIndex flag value //if not provided (will be provided by seeder for performance but normally never) then fetch - if (!localeWordBreakingDataCache.ContainsKey(localeId)) + if (!translationWordBreakingDataCache.ContainsKey(translationId)) { - localeWordBreakingDataCache.Add(localeId, await GetLocaleSearchDataAsync(localeId)); + translationWordBreakingDataCache.Add(translationId, await GetTranslationSearchDataAsync(translationId)); } - var localeWordBreakData = localeWordBreakingDataCache[localeId]; + var translationWordBreakData = translationWordBreakingDataCache[translationId]; int MAXWORDLENGTH = 255; @@ -851,7 +844,7 @@ private static Dictionary localeWordBreakingDataCa //get it as a character char c = t.GetTextElement()[0]; - if (!localeWordBreakData.CJKIndex) + if (!translationWordBreakData.CJKIndex) { #region regular tokenizer @@ -1081,7 +1074,7 @@ private static Dictionary localeWordBreakingDataCa if (s.Length >= MINWORDLENGTH || (KeepWildCards && s.Contains('%'))) { //Add only non stopwords - if (!localeWordBreakData.StopWords.Contains(s)) + if (!translationWordBreakData.StopWords.Contains(s)) { ReturnList.Add(s); } diff --git a/server/AyaNova/biz/LocaleBiz.cs b/server/AyaNova/biz/TranslationBiz.cs similarity index 64% rename from server/AyaNova/biz/LocaleBiz.cs rename to server/AyaNova/biz/TranslationBiz.cs index a1b60697..383e5281 100644 --- a/server/AyaNova/biz/LocaleBiz.cs +++ b/server/AyaNova/biz/TranslationBiz.cs @@ -2,8 +2,6 @@ using System; using System.Linq; using System.Threading.Tasks; using Microsoft.EntityFrameworkCore; -using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.JsonPatch; using AyaNova.Util; using AyaNova.Api.ControllerHelpers; using AyaNova.Models; @@ -11,45 +9,43 @@ using Newtonsoft.Json.Linq; using System.Collections.Generic; using System.Text.RegularExpressions; -using Microsoft.Extensions.DependencyInjection; - namespace AyaNova.Biz { - internal class LocaleBiz : BizObject, IImportAyaNova7Object + internal class TranslationBiz : BizObject, IImportAyaNova7Object { public bool SeedOrImportRelaxedRulesMode { get; set; } - internal LocaleBiz(AyContext dbcontext, long currentUserId, long userLocaleId, AuthorizationRoles userRoles) + internal TranslationBiz(AyContext dbcontext, long currentUserId, long userTranslationId, AuthorizationRoles userRoles) { ct = dbcontext; UserId = currentUserId; - UserLocaleId = userLocaleId; + UserTranslationId = userTranslationId; CurrentUserRoles = userRoles; - BizType = AyaType.Locale; + BizType = AyaType.Translation; SeedOrImportRelaxedRulesMode = false;//default } - internal static LocaleBiz GetBiz(AyContext ct, Microsoft.AspNetCore.Http.HttpContext httpContext = null) + internal static TranslationBiz GetBiz(AyContext ct, Microsoft.AspNetCore.Http.HttpContext httpContext = null) { if (httpContext != null) - return new LocaleBiz(ct, UserIdFromContext.Id(httpContext.Items), UserLocaleIdFromContext.Id(httpContext.Items), UserRolesFromContext.Roles(httpContext.Items)); + return new TranslationBiz(ct, UserIdFromContext.Id(httpContext.Items), UserTranslationIdFromContext.Id(httpContext.Items), UserRolesFromContext.Roles(httpContext.Items)); else - return new LocaleBiz(ct, 1, ServerBootConfig.AYANOVA_DEFAULT_LANGUAGE_ID, AuthorizationRoles.BizAdminFull); + return new TranslationBiz(ct, 1, ServerBootConfig.AYANOVA_DEFAULT_TRANSLATION_ID, AuthorizationRoles.BizAdminFull); } //////////////////////////////////////////////////////////////////////////////////////////////// - //DUPLICATE - only way to create a new locale + //DUPLICATE - only way to create a new translation // - internal async Task DuplicateAsync(NameIdItem inObj) + internal async Task DuplicateAsync(NameIdItem inObj) { //make sure sourceid exists - if (!await LocaleExistsAsync(inObj.Id)) - AddError(ApiErrorCode.VALIDATION_INVALID_VALUE, "Id", "Source locale id does not exist"); + if (!await TranslationExistsAsync(inObj.Id)) + AddError(ApiErrorCode.VALIDATION_INVALID_VALUE, "Id", "Source translation id does not exist"); //Ensure name is unique and not too long and not empty await ValidateAsync(inObj.Name, true); @@ -57,37 +53,37 @@ namespace AyaNova.Biz if (HasErrors) return null; - //fetch the existing locale for duplication - var SourceLocale = await ct.Locale.Include(x => x.LocaleItems).SingleOrDefaultAsync(m => m.Id == inObj.Id); + //fetch the existing translation for duplication + var SourceTranslation = await ct.Translation.Include(x => x.TranslationItems).SingleOrDefaultAsync(m => m.Id == inObj.Id); //replicate the source to a new dest and save - Locale NewLocale = new Locale(); - NewLocale.Name = inObj.Name; + Translation NewTranslation = new Translation(); + NewTranslation.Name = inObj.Name; - NewLocale.Stock = false; - NewLocale.CjkIndex = false; - foreach (LocaleItem i in SourceLocale.LocaleItems) + NewTranslation.Stock = false; + NewTranslation.CjkIndex = false; + foreach (TranslationItem i in SourceTranslation.TranslationItems) { - NewLocale.LocaleItems.Add(new LocaleItem() { Key = i.Key, Display = i.Display }); + NewTranslation.TranslationItems.Add(new TranslationItem() { Key = i.Key, Display = i.Display }); } //Add it to the context so the controller can save it - await ct.Locale.AddAsync(NewLocale); + await ct.Translation.AddAsync(NewTranslation); await ct.SaveChangesAsync(); //Log - await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, NewLocale.Id, AyaType.Locale, AyaEvent.Created), ct); - return NewLocale; + await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, NewTranslation.Id, AyaType.Translation, AyaEvent.Created), ct); + return NewTranslation; } //////////////////////////////////////////////////////////////////////////////////////////////// /// GET - //Get entire locale - internal async Task GetAsync(long fetchId) + //Get entire translation + internal async Task GetAsync(long fetchId) { //This is simple so nothing more here, but often will be copying to a different output object or some other ops - return await ct.Locale.Include(x => x.LocaleItems).SingleOrDefaultAsync(m => m.Id == fetchId); + return await ct.Translation.Include(x => x.TranslationItems).SingleOrDefaultAsync(m => m.Id == fetchId); } @@ -96,7 +92,7 @@ namespace AyaNova.Biz internal async Task> GetPickListAsync() { List l = new List(); - l = await ct.Locale + l = await ct.Translation .AsNoTracking() .OrderBy(m => m.Name) .Select(m => new NameIdItem() @@ -111,10 +107,10 @@ namespace AyaNova.Biz #if (DEBUG) - internal async Task LocaleKeyCoverageAsync() + internal async Task TranslationKeyCoverageAsync() { - AyaNova.Api.Controllers.LocaleController.LocaleCoverageInfo L = new AyaNova.Api.Controllers.LocaleController.LocaleCoverageInfo(); - L.RequestedKeys = ServerBootConfig.LocaleKeysRequested; + AyaNova.Api.Controllers.TranslationController.TranslationCoverageInfo L = new AyaNova.Api.Controllers.TranslationController.TranslationCoverageInfo(); + L.RequestedKeys = ServerBootConfig.TranslationKeysRequested; L.RequestedKeys.Sort(); var AllKeys = await GetKeyListAsync(); foreach (string StockKey in AllKeys) @@ -136,16 +132,16 @@ namespace AyaNova.Biz //or the UI needs to be tested in a way that triggers every key to be used even errors etc internal static void TrackRequestedKey(string key) { - if (!ServerBootConfig.LocaleKeysRequested.Contains(key)) - ServerBootConfig.LocaleKeysRequested.Add(key); + if (!ServerBootConfig.TranslationKeysRequested.Contains(key)) + ServerBootConfig.TranslationKeysRequested.Add(key); } internal static void TrackRequestedKey(List keys) { foreach (string Key in keys) { - if (!ServerBootConfig.LocaleKeysRequested.Contains(Key)) - ServerBootConfig.LocaleKeysRequested.Add(Key); + if (!ServerBootConfig.TranslationKeysRequested.Contains(Key)) + ServerBootConfig.TranslationKeysRequested.Add(Key); } } @@ -158,37 +154,37 @@ namespace AyaNova.Biz #if (DEBUG) TrackRequestedKey(param); #endif - var ret = await ct.LocaleItem.Where(x => x.LocaleId == UserLocaleId && param.Contains(x.Key)).ToDictionaryAsync(x => x.Key, x => x.Display); + var ret = await ct.TranslationItem.Where(x => x.TranslationId == UserTranslationId && param.Contains(x.Key)).ToDictionaryAsync(x => x.Key, x => x.Display); return ret.ToList(); } //Get the keys for a list of keys provided, static format for calling from other internal classes - internal static async Task> GetSubsetStaticAsync(List param, long localeId) + internal static async Task> GetSubsetStaticAsync(List param, long translationId) { #if (DEBUG) TrackRequestedKey(param); #endif AyContext ct = ServiceProviderProvider.DBContext; - if (!await ct.Locale.AnyAsync(e => e.Id == localeId)) - localeId = ServerBootConfig.AYANOVA_DEFAULT_LANGUAGE_ID; - var ret = await ct.LocaleItem.Where(x => x.LocaleId == localeId && param.Contains(x.Key)).AsNoTracking().ToDictionaryAsync(x => x.Key, x => x.Display); + if (!await ct.Translation.AnyAsync(e => e.Id == translationId)) + translationId = ServerBootConfig.AYANOVA_DEFAULT_TRANSLATION_ID; + var ret = await ct.TranslationItem.Where(x => x.TranslationId == translationId && param.Contains(x.Key)).AsNoTracking().ToDictionaryAsync(x => x.Key, x => x.Display); return ret; } - //Get the CJKIndex value for the locale specified - internal static async Task GetCJKIndexAsync(long localeId, AyContext ct = null) + //Get the CJKIndex value for the translation specified + internal static async Task GetCJKIndexAsync(long translationId, AyContext ct = null) { if (ct == null) ct = ServiceProviderProvider.DBContext; - var ret = await ct.Locale.Where(x => x.Id == localeId).AsNoTracking().Select(m => m.CjkIndex).SingleOrDefaultAsync(); + var ret = await ct.Translation.Where(x => x.Id == translationId).AsNoTracking().Select(m => m.CjkIndex).SingleOrDefaultAsync(); return ret; } /// - /// Get the value of the key provided in the default locale chosen + /// Get the value of the key provided in the default translation chosen /// /// /// @@ -200,14 +196,14 @@ namespace AyaNova.Biz TrackRequestedKey(key); #endif AyContext ct = ServiceProviderProvider.DBContext; - return await ct.LocaleItem.Where(m => m.LocaleId == ServerBootConfig.AYANOVA_DEFAULT_LANGUAGE_ID && m.Key == key).Select(m => m.Display).AsNoTracking().FirstOrDefaultAsync(); + return await ct.TranslationItem.Where(m => m.TranslationId == ServerBootConfig.AYANOVA_DEFAULT_TRANSLATION_ID && m.Key == key).Select(m => m.Display).AsNoTracking().FirstOrDefaultAsync(); } //Get all stock keys that are valid (used for import) internal static async Task> GetKeyListAsync() { AyContext ct = ServiceProviderProvider.DBContext; - return await ct.LocaleItem.Where(m => m.LocaleId == 1).OrderBy(m => m.Key).Select(m => m.Key).AsNoTracking().ToListAsync(); + return await ct.TranslationItem.Where(m => m.TranslationId == 1).OrderBy(m => m.Key).Select(m => m.Key).AsNoTracking().ToListAsync(); } @@ -216,12 +212,12 @@ namespace AyaNova.Biz // - internal async Task PutLocaleItemDisplayTextAsync(LocaleItem dbObj, NewTextIdConcurrencyTokenItem inObj, Locale dbParent) + internal async Task PutTranslationItemDisplayTextAsync(TranslationItem dbObj, NewTextIdConcurrencyTokenItem inObj, Translation dbParent) { if (dbParent.Stock == true) { - AddError(ApiErrorCode.INVALID_OPERATION, "object", "LocaleItem is from a Stock locale and cannot be modified"); + AddError(ApiErrorCode.INVALID_OPERATION, "object", "TranslationItem is from a Stock translation and cannot be modified"); return false; } @@ -241,17 +237,17 @@ namespace AyaNova.Biz await ct.SaveChangesAsync(); //Log - await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, dbParent.Id, AyaType.Locale, AyaEvent.Modified), ct); + await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, dbParent.Id, AyaType.Translation, AyaEvent.Modified), ct); return true; } - internal async Task PutLocaleNameAsync(Locale dbObj, NewTextIdConcurrencyTokenItem inObj) + internal async Task PutTranslationNameAsync(Translation dbObj, NewTextIdConcurrencyTokenItem inObj) { if (dbObj.Stock == true) { - AddError(ApiErrorCode.INVALID_OPERATION, "object", "Locale is a Stock locale and cannot be modified"); + AddError(ApiErrorCode.INVALID_OPERATION, "object", "Translation is a Stock translation and cannot be modified"); return false; } @@ -268,7 +264,7 @@ namespace AyaNova.Biz await ct.SaveChangesAsync(); //Log - await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, dbObj.Id, AyaType.Locale, AyaEvent.Modified), ct); + await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, dbObj.Id, AyaType.Translation, AyaEvent.Modified), ct); return true; } @@ -280,16 +276,16 @@ namespace AyaNova.Biz //DELETE // - internal async Task DeleteAsync(Locale dbObj) + internal async Task DeleteAsync(Translation dbObj) { //Determine if the object can be deleted, do the deletion tentatively await ValidateCanDeleteAsync(dbObj); if (HasErrors) return false; - ct.Locale.Remove(dbObj); + ct.Translation.Remove(dbObj); await ct.SaveChangesAsync(); //Log - await EventLogProcessor.DeleteObjectLogAsync(UserId, AyaType.Locale, dbObj.Id, dbObj.Name, ct); + await EventLogProcessor.DeleteObjectLogAsync(UserId, AyaType.Translation, dbObj.Id, dbObj.Name, ct); return true; } @@ -312,7 +308,7 @@ namespace AyaNova.Biz AddError(ApiErrorCode.VALIDATION_LENGTH_EXCEEDED, "Name", "255 char max"); //Name must be unique - if (await ct.Locale.AnyAsync(m => m.Name == inObjName)) + if (await ct.Translation.AnyAsync(m => m.Name == inObjName)) AddError(ApiErrorCode.VALIDATION_NOT_UNIQUE, "Name"); return; @@ -320,25 +316,25 @@ namespace AyaNova.Biz //Can delete? - private async Task ValidateCanDeleteAsync(Locale inObj) + private async Task ValidateCanDeleteAsync(Translation inObj) { //Decided to short circuit these; if there is one issue then return immediately (fail fast rule) - //Ensure it's not a stock locale + //Ensure it's not a stock translation if (inObj.Stock == true) { - AddError(ApiErrorCode.INVALID_OPERATION, "object", "Locale is a Stock locale and cannot be deleted"); + AddError(ApiErrorCode.INVALID_OPERATION, "object", "Translation is a Stock translation and cannot be deleted"); return; } - if (inObj.Id == ServerBootConfig.AYANOVA_DEFAULT_LANGUAGE_ID) + if (inObj.Id == ServerBootConfig.AYANOVA_DEFAULT_TRANSLATION_ID) { - AddError(ApiErrorCode.INVALID_OPERATION, "object", "Locale is set as the default server locale (AYANOVA_DEFAULT_LANGUAGE_ID) and can not be deleted"); + AddError(ApiErrorCode.INVALID_OPERATION, "object", "Translation is set as the default server translation (AYANOVA_DEFAULT_LANGUAGE_ID) and can not be deleted"); return; } - //See if any users exist with this locale selected in which case it's not deleteable - if (await ct.User.AnyAsync(e => e.LocaleId == inObj.Id)) + //See if any users exist with this translation selected in which case it's not deleteable + if (await ct.User.AnyAsync(e => e.TranslationId == inObj.Id)) { AddError(ApiErrorCode.VALIDATION_REFERENTIAL_INTEGRITY, "object", "Can't be deleted in use by one or more Users"); return; @@ -350,61 +346,57 @@ namespace AyaNova.Biz //UTILITIES // - public async Task LocaleNameToIdAsync(string localeName) + public async Task TranslationNameToIdAsync(string translationName) { - var v = await ct.Locale.AsNoTracking().FirstOrDefaultAsync(c => c.Name == localeName); + var v = await ct.Translation.AsNoTracking().FirstOrDefaultAsync(c => c.Name == translationName); if (v == null) return 0; return v.Id; } - public static async Task LocaleNameToIdStaticAsync(string localeName, AyContext ct = null) + public static async Task TranslationNameToIdStaticAsync(string translationName, AyContext ct = null) { if (ct == null) { ct = ServiceProviderProvider.DBContext; } - var v = await ct.Locale.AsNoTracking().FirstOrDefaultAsync(c => c.Name == localeName); - if (v == null) return ServerBootConfig.AYANOVA_DEFAULT_LANGUAGE_ID; + var v = await ct.Translation.AsNoTracking().FirstOrDefaultAsync(c => c.Name == translationName); + if (v == null) return ServerBootConfig.AYANOVA_DEFAULT_TRANSLATION_ID; return v.Id; } - public async Task LocaleExistsAsync(string localeName) + public async Task TranslationExistsAsync(string translationName) { - return await ct.Locale.AnyAsync(c => c.Name == localeName); + return await ct.Translation.AnyAsync(c => c.Name == translationName); } - public async Task LocaleExistsAsync(long id) + public async Task TranslationExistsAsync(long id) { - return await ct.Locale.AnyAsync(e => e.Id == id); + return await ct.Translation.AnyAsync(e => e.Id == id); } - // public static async Task LocaleExistsStaticAsync(long id, AyContext ct) - // { - // return await ct.Locale.AnyAsync(e => e.Id == id); - // } //this is only called by Search.cs to cache a local cjk and stopwords, no one else calls it currently - public static async Task ReturnSpecifiedLocaleIdIfExistsOrDefaultLocaleId(long id, AyContext ct) + public static async Task ReturnSpecifiedTranslationIdIfExistsOrDefaultTranslationId(long id, AyContext ct) { - if (!await ct.Locale.AnyAsync(e => e.Id == id)) - return ServerBootConfig.AYANOVA_DEFAULT_LANGUAGE_ID; + if (!await ct.Translation.AnyAsync(e => e.Id == id)) + return ServerBootConfig.AYANOVA_DEFAULT_TRANSLATION_ID; return id; } - public async Task LocaleItemExistsAsync(long id) + public async Task TranslationItemExistsAsync(long id) { - return await ct.LocaleItem.AnyAsync(e => e.Id == id); + return await ct.TranslationItem.AnyAsync(e => e.Id == id); } /// - /// Used by import, translate the old v7 locale key name into the new shorter version + /// Used by import, translate the old v7 translation key name into the new shorter version /// /// /// - public string Translatev7LocaleKey(string oldKey) + public string Translatev7TranslationKey(string oldKey) { string s = oldKey.Replace(".Label.", ".", StringComparison.InvariantCultureIgnoreCase); if (s.StartsWith("O.", StringComparison.InvariantCultureIgnoreCase)) @@ -483,37 +475,36 @@ namespace AyaNova.Biz return s; } - //LocaleBiz::ImportV7 - old Key "Locale.Label.UI.DestLocale" translates to new Key "LocaleDestLocale" which is not valid! - //LocaleUIDestLocale + /// - /// Ensure stock locales and setup defaults - /// Called by boot preflight check code AFTER it has already ensured the locale is a two letter code if stock one was chosen + /// Ensure stock Translations and setup defaults + /// Called by boot preflight check code AFTER it has already ensured the translation is a two letter code if stock one was chosen /// - public async Task ValidateLocalesAsync() + public async Task ValidateTranslationsAsync() { - //Ensure default locales are present and that there is a server default locale that exists + //Ensure default translations are present and that there is a server default translation that exists - if (!await LocaleExistsAsync("en")) + if (!await TranslationExistsAsync("en")) { - throw new System.Exception($"E1015: stock locale English (en) not found in database!"); + throw new System.Exception($"E1015: stock translation English (en) not found in database!"); } - if (!await LocaleExistsAsync("es")) + if (!await TranslationExistsAsync("es")) { - throw new System.Exception($"E1015: stock locale Spanish (es) not found in database!"); + throw new System.Exception($"E1015: stock translation Spanish (es) not found in database!"); } - if (!await LocaleExistsAsync("de")) + if (!await TranslationExistsAsync("de")) { - throw new System.Exception($"E1015: stock locale German (de) not found in database!"); + throw new System.Exception($"E1015: stock translation German (de) not found in database!"); } - if (!await LocaleExistsAsync("fr")) + if (!await TranslationExistsAsync("fr")) { - throw new System.Exception($"E1015: stock locale French (fr) not found in database!"); + throw new System.Exception($"E1015: stock translation French (fr) not found in database!"); } - //Ensure chosen default locale exists - switch (ServerBootConfig.AYANOVA_DEFAULT_LANGUAGE) + //Ensure chosen default translation exists + switch (ServerBootConfig.AYANOVA_DEFAULT_TRANSLATION) { case "en": case "es": @@ -521,16 +512,16 @@ namespace AyaNova.Biz case "fr": break; default: - if (!await LocaleExistsAsync(ServerBootConfig.AYANOVA_DEFAULT_LANGUAGE)) + if (!await TranslationExistsAsync(ServerBootConfig.AYANOVA_DEFAULT_TRANSLATION)) { - throw new System.Exception($"E1015: stock locale {ServerBootConfig.AYANOVA_DEFAULT_LANGUAGE} not found in database!"); + throw new System.Exception($"E1015: stock translation {ServerBootConfig.AYANOVA_DEFAULT_TRANSLATION} not found in database!"); } break; } - //Put the default locale ID number into the ServerBootConfig for later use - ServerBootConfig.AYANOVA_DEFAULT_LANGUAGE_ID = await LocaleNameToIdAsync(ServerBootConfig.AYANOVA_DEFAULT_LANGUAGE); + //Put the default translation ID number into the ServerBootConfig for later use + ServerBootConfig.AYANOVA_DEFAULT_TRANSLATION_ID = await TranslationNameToIdAsync(ServerBootConfig.AYANOVA_DEFAULT_TRANSLATION); } @@ -546,17 +537,17 @@ namespace AyaNova.Biz { case "main": { - //Get source locale name from filename using regex - var SourceLocaleFileName = j["V7_SOURCE_FILE_NAME"].Value(); - Regex RxExtractLocaleName = new Regex(@"locale\.(.*)\.json"); - var v = RxExtractLocaleName.Match(SourceLocaleFileName); - var SourceLocaleName = v.Groups[1].ToString(); + //Get source translation name from filename using regex + var SourceTranslationFileName = j["V7_SOURCE_FILE_NAME"].Value(); + Regex RxExtractTranslationName = new Regex(@"translation\.(.*)\.json"); + var v = RxExtractTranslationName.Match(SourceTranslationFileName); + var SourceTranslationName = v.Groups[1].ToString(); //Ensure doesn't already exist - if (await LocaleExistsAsync(SourceLocaleName)) + if (await TranslationExistsAsync(SourceTranslationName)) { //If there are any validation errors, log in joblog and move on - await JobsBiz.LogJobAsync(jobId, $"LocaleBiz::ImportV7Async -> - Locale \"{SourceLocaleName}\" already exists in database, can not import over an existing locale", ct); + await JobsBiz.LogJobAsync(jobId, $"TranslationBiz::ImportV7Async -> - Translation \"{SourceTranslationName}\" already exists in database, can not import over an existing translation", ct); return false; } @@ -568,7 +559,7 @@ namespace AyaNova.Biz SkipKeys.Add("IMPORT_TASK"); List ValidKeys = await GetKeyListAsync(); - Dictionary NewLocaleDict = new Dictionary(); + Dictionary NewTranslationDict = new Dictionary(); foreach (var Pair in j.Children()) { var V7Value = Pair.First.Value().Replace(" && ", " ").Replace(" & ", " ").Replace("&", "");//clean out LT values that had double ampersands for old Windows menu shortcut scheme @@ -576,57 +567,57 @@ namespace AyaNova.Biz if (!SkipKeys.Contains(V7KeyName)) { - var RavenKeyName = Translatev7LocaleKey(V7KeyName); + var RavenKeyName = Translatev7TranslationKey(V7KeyName); if (!ValidKeys.Contains(RavenKeyName)) { - throw new System.ArgumentOutOfRangeException($"LocaleBiz::ImportV7 - old Key \"{V7KeyName}\" translates to new Key \"{RavenKeyName}\" which is not valid!"); + throw new System.ArgumentOutOfRangeException($"TranslationBiz::ImportV7 - old Key \"{V7KeyName}\" translates to new Key \"{RavenKeyName}\" which is not valid!"); } - if (!NewLocaleDict.ContainsKey(RavenKeyName)) + if (!NewTranslationDict.ContainsKey(RavenKeyName)) { - NewLocaleDict.Add(RavenKeyName, V7Value); + NewTranslationDict.Add(RavenKeyName, V7Value); } else { //Use the shortest V7Value string in the case of dupes - if (NewLocaleDict[RavenKeyName].Length > V7Value.Length) + if (NewTranslationDict[RavenKeyName].Length > V7Value.Length) { - NewLocaleDict[RavenKeyName] = V7Value; + NewTranslationDict[RavenKeyName] = V7Value; } } } } - //Now add keys that were added after v7 for RAVEN using default locale values + //Now add keys that were added after v7 for RAVEN using default translation values foreach (string s in ValidKeys) { - if (!NewLocaleDict.ContainsKey(s)) + if (!NewTranslationDict.ContainsKey(s)) { - NewLocaleDict.Add(s, await GetDefaultLocalizedTextAsync(s)); + NewTranslationDict.Add(s, await GetDefaultLocalizedTextAsync(s)); } } //Validate it's the correct number of keys expected - if (NewLocaleDict.Count != ValidKeys.Count) + if (NewTranslationDict.Count != ValidKeys.Count) { - throw new System.ArgumentOutOfRangeException($"LocaleBiz::ImportV7 - Import locale \"{SourceLocaleName}\" has an unexpected number of keys: {NewLocaleDict.Count}, expected {ValidKeys.Count} "); + throw new System.ArgumentOutOfRangeException($"TranslationBiz::ImportV7 - Import translation \"{SourceTranslationName}\" has an unexpected number of keys: {NewTranslationDict.Count}, expected {ValidKeys.Count} "); } //have file name, have all localized text - Locale l = new Locale(); - l.Name = SourceLocaleName; + Translation l = new Translation(); + l.Name = SourceTranslationName; l.Stock = false; - foreach (KeyValuePair K in NewLocaleDict) + foreach (KeyValuePair K in NewTranslationDict) { - l.LocaleItems.Add(new LocaleItem() { Key = K.Key, Display = K.Value }); + l.TranslationItems.Add(new TranslationItem() { Key = K.Key, Display = K.Value }); } - await ct.Locale.AddAsync(l); + await ct.Translation.AddAsync(l); await ct.SaveChangesAsync(); //Log now that we have the Id, note that there is no source created / modified for this so just attributing to current userId - await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, l.Id, AyaType.Locale, AyaEvent.Created), ct); + await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, l.Id, AyaType.Translation, AyaEvent.Created), ct); } break; diff --git a/server/AyaNova/biz/UserBiz.cs b/server/AyaNova/biz/UserBiz.cs index 7c80cda3..6c4d629d 100644 --- a/server/AyaNova/biz/UserBiz.cs +++ b/server/AyaNova/biz/UserBiz.cs @@ -19,11 +19,11 @@ namespace AyaNova.Biz public bool SeedOrImportRelaxedRulesMode { get; set; } - internal UserBiz(AyContext dbcontext, long currentUserId, long userLocaleId, AuthorizationRoles userRoles) + internal UserBiz(AyContext dbcontext, long currentUserId, long userTranslationId, AuthorizationRoles userRoles) { ct = dbcontext; UserId = currentUserId; - UserLocaleId = userLocaleId; + UserTranslationId = userTranslationId; CurrentUserRoles = userRoles; BizType = AyaType.User; SeedOrImportRelaxedRulesMode = false;//default @@ -41,9 +41,9 @@ namespace AyaNova.Biz internal static UserBiz GetBiz(AyContext ct, Microsoft.AspNetCore.Http.HttpContext httpContext = null) { if (httpContext != null) - return new UserBiz(ct, UserIdFromContext.Id(httpContext.Items), UserLocaleIdFromContext.Id(httpContext.Items), UserRolesFromContext.Roles(httpContext.Items)); + return new UserBiz(ct, UserIdFromContext.Id(httpContext.Items), UserTranslationIdFromContext.Id(httpContext.Items), UserRolesFromContext.Roles(httpContext.Items)); else//when called internally for internal ops there will be no context so need to set default values for that - return new UserBiz(ct, 1, ServerBootConfig.AYANOVA_DEFAULT_LANGUAGE_ID, AuthorizationRoles.BizAdminFull); + return new UserBiz(ct, 1, ServerBootConfig.AYANOVA_DEFAULT_TRANSLATION_ID, AuthorizationRoles.BizAdminFull); } @@ -214,7 +214,7 @@ namespace AyaNova.Biz private async Task SearchIndexAsync(User obj, bool isNew) { //SEARCH INDEXING - var SearchParams = new Search.SearchIndexProcessObjectParameters(UserLocaleId, obj.Id, BizType, obj.Name); + var SearchParams = new Search.SearchIndexProcessObjectParameters(UserTranslationId, obj.Id, BizType, obj.Name); SearchParams.AddText(obj.Notes).AddText(obj.Name).AddText(obj.EmployeeNumber).AddText(obj.Tags).AddCustomFields(obj.CustomFields); if (isNew) @@ -456,7 +456,7 @@ namespace AyaNova.Biz Active = o.Active, Name = o.Name, Roles = o.Roles, - LocaleId = o.LocaleId, + TranslationId = o.TranslationId, UserType = o.UserType, EmployeeNumber = o.EmployeeNumber, Notes = o.Notes, @@ -672,8 +672,8 @@ namespace AyaNova.Biz //No rights i.Roles = AuthorizationRoles.NoRole; - //temporary locale id to satisfy db settings - i.LocaleId = ServerBootConfig.AYANOVA_DEFAULT_LANGUAGE_ID; + //temporary translation id to satisfy db settings + i.TranslationId = ServerBootConfig.AYANOVA_DEFAULT_TRANSLATION_ID; User o = await CreateAsync(i); if (HasErrors) @@ -702,62 +702,62 @@ namespace AyaNova.Biz await ImportAyaNova7Biz.LogEventCreatedModifiedEventsAsync(j, importMap, BizType, ct); } break; - case "locale": + case "translation": { - #region set locale + #region set translation //get the userId //---- var V7Id = new Guid(j["ID"].Value()); var MapItem = importMap.Where(m => m.V7ObjectId == V7Id).FirstOrDefault(); if (MapItem == null) { - throw new System.Exception("UserBiz::ImportV7Async-locale - FATAL ERROR, IMPORT FROM V7 CANNOT CONTINUE USER NOT FOUND IN IMPORTMAP"); + throw new System.Exception("UserBiz::ImportV7Async-translation - FATAL ERROR, IMPORT FROM V7 CANNOT CONTINUE USER NOT FOUND IN IMPORTMAP"); } var NewId = MapItem.NewObjectAyaTypeId.ObjectId; User u = ct.User.Where(m => m.Id == NewId).FirstOrDefault(); if (u == null) { - throw new System.Exception("UserBiz::ImportV7Async-locale - FATAL ERROR, IMPORT FROM V7 CANNOT CONTINUE USER NOT FOUND IN DATABASE"); + throw new System.Exception("UserBiz::ImportV7Async-translation - FATAL ERROR, IMPORT FROM V7 CANNOT CONTINUE USER NOT FOUND IN DATABASE"); } - //handle locale entries for users now that we have the locales created - var V7Locale = j["DefaultLanguage"].Value(); + //handle translation entries for users now that we have the Translations created + var V7Translation = j["DefaultLanguage"].Value(); - //Get new locale name - var NewLocaleName = string.Empty; - switch (V7Locale) + //Get new translation name + var NewTranslationName = string.Empty; + switch (V7Translation) { case "Français": - NewLocaleName = "fr"; + NewTranslationName = "fr"; break; case "Español": - NewLocaleName = "es"; + NewTranslationName = "es"; break; case "Deutsch": - NewLocaleName = "de"; + NewTranslationName = "de"; break; case "English": - NewLocaleName = "en"; + NewTranslationName = "en"; break; default: { - //It's a custom locale, translate it from v7 original format to imported name format + //It's a custom translation, translate it from v7 original format to imported name format //make lower and replace spaces with dashes - NewLocaleName = V7Locale.ToLowerInvariant().Replace(" ", "-"); + NewTranslationName = V7Translation.ToLowerInvariant().Replace(" ", "-"); //ensure each character is a valid path character foreach (char c in System.IO.Path.GetInvalidFileNameChars())//is this kosher on linux? Original code was windows { - NewLocaleName = NewLocaleName.Replace(c, '_'); + NewTranslationName = NewTranslationName.Replace(c, '_'); } } break; } - u.LocaleId = await LocaleBiz.LocaleNameToIdStaticAsync(NewLocaleName, ct); + u.TranslationId = await TranslationBiz.TranslationNameToIdStaticAsync(NewTranslationName, ct); ct.SaveChanges(); - #endregion set locale + #endregion set translation } break; diff --git a/server/AyaNova/biz/WidgetBiz.cs b/server/AyaNova/biz/WidgetBiz.cs index 6fee30aa..92d606ae 100644 --- a/server/AyaNova/biz/WidgetBiz.cs +++ b/server/AyaNova/biz/WidgetBiz.cs @@ -12,11 +12,11 @@ namespace AyaNova.Biz internal class WidgetBiz : BizObject, IJobObject { - internal WidgetBiz(AyContext dbcontext, long currentUserId, long userLocaleId, AuthorizationRoles UserRoles) + internal WidgetBiz(AyContext dbcontext, long currentUserId, long userTranslationId, AuthorizationRoles UserRoles) { ct = dbcontext; UserId = currentUserId; - UserLocaleId = userLocaleId; + UserTranslationId = userTranslationId; CurrentUserRoles = UserRoles; BizType = AyaType.Widget; } @@ -25,9 +25,9 @@ namespace AyaNova.Biz { if (httpContext != null) - return new WidgetBiz(ct, UserIdFromContext.Id(httpContext.Items), UserLocaleIdFromContext.Id(httpContext.Items), UserRolesFromContext.Roles(httpContext.Items)); + return new WidgetBiz(ct, UserIdFromContext.Id(httpContext.Items), UserTranslationIdFromContext.Id(httpContext.Items), UserRolesFromContext.Roles(httpContext.Items)); else//when called internally for internal ops there will be no context so need to set default values for that - return new WidgetBiz(ct, 1, ServerBootConfig.AYANOVA_DEFAULT_LANGUAGE_ID, AuthorizationRoles.BizAdminFull); + return new WidgetBiz(ct, 1, ServerBootConfig.AYANOVA_DEFAULT_TRANSLATION_ID, AuthorizationRoles.BizAdminFull); } @@ -201,7 +201,7 @@ namespace AyaNova.Biz private async Task SearchIndexAsync(Widget obj, bool isNew) { //SEARCH INDEXING - var SearchParams = new Search.SearchIndexProcessObjectParameters(UserLocaleId, obj.Id, BizType, obj.Name); + var SearchParams = new Search.SearchIndexProcessObjectParameters(UserTranslationId, obj.Id, BizType, obj.Name); SearchParams.AddText(obj.Notes).AddText(obj.Name).AddText(obj.Serial).AddText(obj.Tags).AddCustomFields(obj.CustomFields); diff --git a/server/AyaNova/models/AyContext.cs b/server/AyaNova/models/AyContext.cs index 6abc21e2..f1fb38d4 100644 --- a/server/AyaNova/models/AyContext.cs +++ b/server/AyaNova/models/AyContext.cs @@ -15,8 +15,8 @@ namespace AyaNova.Models public virtual DbSet FileAttachment { get; set; } public virtual DbSet OpsJob { get; set; } public virtual DbSet OpsJobLog { get; set; } - public virtual DbSet Locale { get; set; } - public virtual DbSet LocaleItem { get; set; } + public virtual DbSet Translation { get; set; } + public virtual DbSet TranslationItem { get; set; } public virtual DbSet DataListView { get; set; } public virtual DbSet Tag { get; set; } public virtual DbSet FormCustom { get; set; } @@ -82,9 +82,9 @@ namespace AyaNova.Models modelBuilder.Entity().HasIndex(p => p.StoredFileName); //Relationships - modelBuilder.Entity() - .HasMany(c => c.LocaleItems) - .WithOne(e => e.Locale) + modelBuilder.Entity() + .HasMany(c => c.TranslationItems) + .WithOne(e => e.Translation) .IsRequired();//default delete behaviour is cascade when set to isrequired modelBuilder.Entity() diff --git a/server/AyaNova/models/Locale.cs b/server/AyaNova/models/Locale.cs index 14dc74de..36d2162a 100644 --- a/server/AyaNova/models/Locale.cs +++ b/server/AyaNova/models/Locale.cs @@ -7,7 +7,7 @@ using Newtonsoft.Json; namespace AyaNova.Models { // [JsonObject(IsReference = true)] - public partial class Locale + public partial class Translation { public long Id { get; set; } public uint ConcurrencyToken { get; set; } @@ -18,7 +18,7 @@ namespace AyaNova.Models public bool? Stock { get; set; } public bool CjkIndex { get; set; } - //TODO: Defaults for user options locale settings: + //TODO: Defaults for user options translation settings: // short date, short time formats // currency symbol //digit grouping separator symbol @@ -27,18 +27,18 @@ namespace AyaNova.Models //Relationship //was this but.. - // public ICollection LocaleItems { get; set; } + // public ICollection TranslationItems { get; set; } //Not perhaps so useful here but this is a good way to lazy initialize collections which //is more efficient when there are many child collections (workorder) and means no need to null check the collection //https://stackoverflow.com/a/20773057/8939 - private ICollection _localeItem; - public virtual ICollection LocaleItems + private ICollection _translationItem; + public virtual ICollection TranslationItems { get { - return this._localeItem ?? (this._localeItem = new HashSet()); + return this._translationItem ?? (this._translationItem = new HashSet()); } } diff --git a/server/AyaNova/models/LocaleItem.cs b/server/AyaNova/models/LocaleItem.cs index c3ea9a15..2be1da17 100644 --- a/server/AyaNova/models/LocaleItem.cs +++ b/server/AyaNova/models/LocaleItem.cs @@ -9,7 +9,7 @@ using Newtonsoft.Json; namespace AyaNova.Models { - public partial class LocaleItem + public partial class TranslationItem { public long Id { get; set; } public uint ConcurrencyToken { get; set; } @@ -19,10 +19,10 @@ namespace AyaNova.Models [Required] public string Display { get; set; } - public long LocaleId { get; set; } + public long TranslationId { get; set; } //Relation [JsonIgnore] - public Locale Locale { get; set; } + public Translation Translation { get; set; } } } diff --git a/server/AyaNova/models/User.cs b/server/AyaNova/models/User.cs index 3166fde0..af3d0c35 100644 --- a/server/AyaNova/models/User.cs +++ b/server/AyaNova/models/User.cs @@ -23,7 +23,7 @@ namespace AyaNova.Models [Required] public AuthorizationRoles Roles { get; set; } [Required] - public long LocaleId { get; set; } + public long TranslationId { get; set; } public string DlKey { get; set; } public DateTime? DlKeyExpire { get; set; } diff --git a/server/AyaNova/resource/de.json b/server/AyaNova/resource/de.json index 4bc60cfe..ac403294 100644 --- a/server/AyaNova/resource/de.json +++ b/server/AyaNova/resource/de.json @@ -368,18 +368,18 @@ "LoanItemRateWeek": "Week rate", "LoanItemRateYear": "Year rate", "LoanItemSerial": "Seriennummer", - "LocaleCustomizeText": "Customize text", - "LocaleExport": "Gebietsschema in Datei exportieren", - "LocaleImport": "Gebietsschema aus Datei importieren", - "LocaleList": "Lokalisierte Textsammlung", - "LocaleLocaleFile": "AyaNova übertragbare Gebietsschemadatei (*.xml)", - "LocaleUIDestLocale": "Neuer Name für Gebietsschema", - "LocaleUISourceLocale": "Quellgebietsschema", - "LocaleWarnLocaleLocked": "Your user account is using the \"English\" locale text.\r\nThis locale is read only and can not be edited.\r\nPlease change your locale in your user settings to any other value than \"English\" to proceed.", - "LocalizedTextDisplayText": "Standardanzeigetext", - "LocalizedTextDisplayTextCustom": "Angepasster Anzeigetext", - "LocalizedTextKey": "Schlüssel", - "LocalizedTextLocale": "Sprache", + "TranslationCustomizeText": "Customize text", + "TranslationExport": "Gebietsschema in Datei exportieren", + "TranslationImport": "Gebietsschema aus Datei importieren", + "TranslationList": "Lokalisierte Textsammlung", + "TranslationFile": "AyaNova übertragbare Gebietsschemadatei (*.xml)", + "TranslationDest": "Neuer Name für Gebietsschema", + "TranslationSource": "Quellgebietsschema", + "TranslationWarnLocked": "Your user account is using the \"English\" translation text.\r\nThis translation is read only and can not be edited.\r\nPlease change your translation in your user settings to any other value than \"English\" to proceed.", + "TranslationDisplayText": "Standardanzeigetext", + "TranslationDisplayTextCustom": "Angepasster Anzeigetext", + "TranslationKey": "Schlüssel", + "Translation": "Übersetzung", "MemoForward": "Weiterleiten", "MemoReply": "Antworten", "MemoEventCreated": "Memo - eingehend", @@ -450,7 +450,7 @@ "HeadOffice": "Hauptsitz", "LoanItem": "Leihposten", "Locale": "Gebietsschema", - "LocalizedText": "Lokalisierter Text", + "TranslatedText": "Übersetzter Text", "Maintenance": "AyaNova - Interne Wartung", "Memo": "Memo", "NameFetcher": "Namenabrufer-Objekt", diff --git a/server/AyaNova/resource/en.json b/server/AyaNova/resource/en.json index 77c86679..b20aef16 100644 --- a/server/AyaNova/resource/en.json +++ b/server/AyaNova/resource/en.json @@ -368,18 +368,18 @@ "LoanItemRateWeek": "Week rate", "LoanItemRateYear": "Year rate", "LoanItemSerial": "Serial number", - "LocaleCustomizeText": "Customize text", - "LocaleExport": "Export locale to file", - "LocaleImport": "Import locale from file", - "LocaleList": "Localized text collection", - "LocaleLocaleFile": "AyaNova transportable Locale file (*.xml)", - "LocaleUIDestLocale": "New locale name", - "LocaleUISourceLocale": "Source locale", - "LocaleWarnLocaleLocked": "Your user account is using the \"English\" locale text.\r\nThis locale is read only and can not be edited.\r\nPlease change your locale in your user settings to any other value than \"English\" to proceed.", - "LocalizedTextDisplayText": "Standard display text", - "LocalizedTextDisplayTextCustom": "Custom display text", - "LocalizedTextKey": "Key", - "LocalizedTextLocale": "Language", + "TranslationCustomizeText": "Customize text", + "TranslationExport": "Export translation to file", + "TranslationImport": "Import translation from file", + "TranslationList": "Translation text collection", + "TranslationFile": "AyaNova transportable Translation file (*.xml)", + "TranslationDest": "New translation name", + "TranslationSource": "Source translation", + "TranslationWarnLocked": "Your user account is using the \"English\" translation text.\r\nThis translation is read only and can not be edited.\r\nPlease change your translation in your user settings to any other value than \"English\" to proceed.", + "TranslationDisplayText": "Standard display text", + "TranslationDisplayTextCustom": "Custom display text", + "TranslationKey": "Key", + "Translation": "Translation", "MemoForward": "Forward", "MemoReply": "Reply", "MemoEventCreated": "Memo - incoming", @@ -449,8 +449,8 @@ "GridFilter": "GridFilter", "HeadOffice": "Head Office", "LoanItem": "Loan item", - "Locale": "Locale", - "LocalizedText": "Localized text", + "Locale": "Translation", + "TranslatedText": "Translated text", "Maintenance": "AyaNova internal maintenance", "Memo": "Memo", "NameFetcher": "NameFetcher object", diff --git a/server/AyaNova/resource/es.json b/server/AyaNova/resource/es.json index 413adb3e..60964e3c 100644 --- a/server/AyaNova/resource/es.json +++ b/server/AyaNova/resource/es.json @@ -368,18 +368,18 @@ "LoanItemRateWeek": "Week rate", "LoanItemRateYear": "Year rate", "LoanItemSerial": "Número de serie", - "LocaleCustomizeText": "Customize text", - "LocaleExport": "Exportar localización en archivo", - "LocaleImport": "Importar localización desde archivo", - "LocaleList": "Colección texto localizado", - "LocaleLocaleFile": "Archivo de localización transportable AyaNova (*.xml)", - "LocaleUIDestLocale": "Nuevo nombre localización", - "LocaleUISourceLocale": "Localización origen", - "LocaleWarnLocaleLocked": "Your user account is using the \"English\" locale text.\r\nThis locale is read only and can not be edited.\r\nPlease change your locale in your user settings to any other value than \"English\" to proceed.", - "LocalizedTextDisplayText": "Texto estándar de visualización", - "LocalizedTextDisplayTextCustom": "Texto campo personalizado", - "LocalizedTextKey": "Clave", - "LocalizedTextLocale": "Idioma", + "TranslationCustomizeText": "Customize text", + "TranslationExport": "Exportar localización en archivo", + "TranslationImport": "Importar localización desde archivo", + "TranslationList": "Colección texto localizado", + "TranslationFile": "Archivo de localización transportable AyaNova (*.xml)", + "TranslationDest": "Nuevo nombre localización", + "TranslationSource": "Localización origen", + "TranslationWarnLocked": "Your user account is using the \"English\" translation text.\r\nThis translation is read only and can not be edited.\r\nPlease change your translation in your user settings to any other value than \"English\" to proceed.", + "TranslationDisplayText": "Texto estándar de visualización", + "TranslationDisplayTextCustom": "Texto campo personalizado", + "TranslationKey": "Clave", + "Translation": "Traducción", "MemoForward": "Reenviar", "MemoReply": "Respuesta", "MemoEventCreated": "Memorándum - entrada", @@ -450,7 +450,7 @@ "HeadOffice": "Sede", "LoanItem": "Elemento en préstamo", "Locale": "Localización", - "LocalizedText": "Texto localizado", + "TranslatedText": "Texto traducido", "Maintenance": "Mantenimiento interno AyaNova", "Memo": "Memorándum", "NameFetcher": "Objeto recopilador de nombres", diff --git a/server/AyaNova/resource/fr.json b/server/AyaNova/resource/fr.json index d57f1876..38e86989 100644 --- a/server/AyaNova/resource/fr.json +++ b/server/AyaNova/resource/fr.json @@ -368,18 +368,18 @@ "LoanItemRateWeek": "Week rate", "LoanItemRateYear": "Year rate", "LoanItemSerial": "Numéro de série", - "LocaleCustomizeText": "Customize text", - "LocaleExport": "Exporter les paramètres régionaux dans le fichier", - "LocaleImport": "Importer les paramètres régionaux du fichier", - "LocaleList": "Ensemble de textes localisés", - "LocaleLocaleFile": "Fichier transportable de paramètres régionaux AyaNova (*.xml)", - "LocaleUIDestLocale": "Nouveau nom de paramètres régionaux", - "LocaleUISourceLocale": "Paramètres régionaux source", - "LocaleWarnLocaleLocked": "Your user account is using the \"English\" locale text.\r\nThis locale is read only and can not be edited.\r\nPlease change your locale in your user settings to any other value than \"English\" to proceed.", - "LocalizedTextDisplayText": "Texte standard", - "LocalizedTextDisplayTextCustom": "Texte personnalisé", - "LocalizedTextKey": "Clé", - "LocalizedTextLocale": "Langue", + "TranslationCustomizeText": "Customize text", + "TranslationExport": "Exporter les paramètres régionaux dans le fichier", + "TranslationImport": "Importer les paramètres régionaux du fichier", + "TranslationList": "Ensemble de textes localisés", + "TranslationFile": "Fichier transportable de paramètres régionaux AyaNova (*.xml)", + "TranslationDest": "Nouveau nom de paramètres régionaux", + "TranslationSource": "Paramètres régionaux source", + "TranslationWarnLocked": "Your user account is using the \"English\" translation text.\r\nThis translation is read only and can not be edited.\r\nPlease change your translation in your user settings to any other value than \"English\" to proceed.", + "TranslationDisplayText": "Texte standard", + "TranslationDisplayTextCustom": "Texte personnalisé", + "TranslationKey": "Clé", + "Translation": "Traduction", "MemoForward": "Faire suivre", "MemoReply": "Répondre", "MemoEventCreated": "Mémo - entrant", @@ -450,7 +450,7 @@ "HeadOffice": "Siège social", "LoanItem": "Élément de prêt", "Locale": "Paramètres linguistiques", - "LocalizedText": "Texte localisé", + "TranslatedText": "Texte traduit", "Maintenance": "Maintenance interne AyaNova", "Memo": "Mémo", "NameFetcher": "Objet NameFetcher", diff --git a/server/AyaNova/util/AySchema.cs b/server/AyaNova/util/AySchema.cs index 47cb8641..a322f120 100644 --- a/server/AyaNova/util/AySchema.cs +++ b/server/AyaNova/util/AySchema.cs @@ -150,25 +150,25 @@ namespace AyaNova.Util await ExecQueryAsync("CREATE TABLE asearchkey (id BIGSERIAL PRIMARY KEY, wordid bigint not null REFERENCES asearchdictionary (id), objectid bigint not null, objecttype integer not null, inname bool not null)"); - //create locale text tables - await ExecQueryAsync("CREATE TABLE alocale (id BIGSERIAL PRIMARY KEY, name varchar(255) not null, stock bool, cjkindex bool default false)"); + //create translation text tables + await ExecQueryAsync("CREATE TABLE atranslation (id BIGSERIAL PRIMARY KEY, name varchar(255) not null, stock bool, cjkindex bool default false)"); //LOOKAT: I don't think this is doing anything: - //exec("CREATE UNIQUE INDEX alocale_name_idx ON alocale (name)"); + //exec("CREATE UNIQUE INDEX atranslation_name_idx ON atranslation (name)"); - await ExecQueryAsync("CREATE TABLE alocaleitem (id BIGSERIAL PRIMARY KEY, localeid bigint not null REFERENCES alocale (id), key text not null, display text not null)"); + await ExecQueryAsync("CREATE TABLE atranslationitem (id BIGSERIAL PRIMARY KEY, translationid bigint not null REFERENCES atranslation (id), key text not null, display text not null)"); //LOOKAT: this is for what exactly?? - // exec("CREATE INDEX alocaleitem_localeid_key_idx ON alocaleitem (localeid,key)"); + // exec("CREATE INDEX atranslationitem_translationid_key_idx ON atranslationitem (translationid,key)"); //This seems more appropriate - await ExecQueryAsync("CREATE INDEX alocaleitem_localeid_key_display_idx ON alocaleitem (localeid,key, display)"); + await ExecQueryAsync("CREATE INDEX atranslationitem_translationid_key_display_idx ON atranslationitem (translationid,key, display)"); - //Load the default LOCALES - await AyaNova.Biz.PrimeData.PrimeLocales(); + //Load the default TRANSLATIONS + await AyaNova.Biz.PrimeData.PrimeTranslations(); //Add user table await ExecQueryAsync("CREATE TABLE auser (id BIGSERIAL PRIMARY KEY, active bool not null, name varchar(255) not null unique, " + - "login text not null, password text not null, salt text not null, roles integer not null, localeid bigint not null REFERENCES alocale (id), " + + "login text not null, password text not null, salt text not null, roles integer not null, translationid bigint not null REFERENCES atranslation (id), " + "dlkey text, dlkeyexpire timestamp, usertype integer not null, employeenumber varchar(255), notes text, customerid bigint, " + "headofficeid bigint, subvendorid bigint, customfields text, tags varchar(255) ARRAY)"); diff --git a/server/AyaNova/util/FileUtil.cs b/server/AyaNova/util/FileUtil.cs index 36bf29be..f24a8662 100644 --- a/server/AyaNova/util/FileUtil.cs +++ b/server/AyaNova/util/FileUtil.cs @@ -195,7 +195,7 @@ namespace AyaNova.Util string text = reader.ReadToEnd(); var j = JObject.Parse(text); - //Here add v7 import file name as sometimes it's needed later (locales) + //Here add v7 import file name as sometimes it's needed later (Translations) j.Add("V7_SOURCE_FILE_NAME", JToken.FromObject(importFileName)); jList.Add(j); } diff --git a/server/AyaNova/util/Seeder.cs b/server/AyaNova/util/Seeder.cs index 85795c3a..1dc72652 100644 --- a/server/AyaNova/util/Seeder.cs +++ b/server/AyaNova/util/Seeder.cs @@ -508,10 +508,10 @@ namespace AyaNova.Util //TEST NOT ACTIVE - this is used for a test to see if inactive user can login await GenSeedUserAsync(log, 1, AuthorizationRoles.OpsAdminLimited, UserType.NonSchedulable, false, "TEST_INACTIVE", "TEST_INACTIVE"); - //Alternate locale users for each stock locale - await GenSeedUserAsync(log, 1, AuthorizationRoles.All, UserType.Administrator, true, "de", "de", await LocaleBiz.LocaleNameToIdStaticAsync("de")); - await GenSeedUserAsync(log, 1, AuthorizationRoles.All, UserType.Administrator, true, "es", "es", await LocaleBiz.LocaleNameToIdStaticAsync("es")); - await GenSeedUserAsync(log, 1, AuthorizationRoles.All, UserType.Administrator, true, "fr", "fr", await LocaleBiz.LocaleNameToIdStaticAsync("fr")); + //Alternate translation users for each stock translation + await GenSeedUserAsync(log, 1, AuthorizationRoles.All, UserType.Administrator, true, "de", "de", await TranslationBiz.TranslationNameToIdStaticAsync("de")); + await GenSeedUserAsync(log, 1, AuthorizationRoles.All, UserType.Administrator, true, "es", "es", await TranslationBiz.TranslationNameToIdStaticAsync("es")); + await GenSeedUserAsync(log, 1, AuthorizationRoles.All, UserType.Administrator, true, "fr", "fr", await TranslationBiz.TranslationNameToIdStaticAsync("fr")); } @@ -548,10 +548,10 @@ namespace AyaNova.Util public static async Task GenSeedUserAsync(ILogger log, int count, AuthorizationRoles roles, UserType userType, - bool active = true, string login = null, string password = null, long localeId = 0) + bool active = true, string login = null, string password = null, long translationId = 0) { - if (localeId == 0) - localeId = ServerBootConfig.AYANOVA_DEFAULT_LANGUAGE_ID; + if (translationId == 0) + translationId = ServerBootConfig.AYANOVA_DEFAULT_TRANSLATION_ID; //Don't do the following commented out, it's slower // using (var ct = ServiceProviderProvider.DBContext) @@ -582,7 +582,7 @@ namespace AyaNova.Util else u.Password = u.Login; u.Roles = roles; - u.LocaleId = localeId; + u.TranslationId = translationId; u.UserType = userType; u.EmployeeNumber = "A-" + (454 + SeededUserCount).ToString() + "-Y"; u.Notes = Fake.Lorem.Sentence();//Fake.Lorem.Paragraph(2); diff --git a/server/AyaNova/util/ServerBootConfig.cs b/server/AyaNova/util/ServerBootConfig.cs index 6a6efe3c..58420cef 100644 --- a/server/AyaNova/util/ServerBootConfig.cs +++ b/server/AyaNova/util/ServerBootConfig.cs @@ -22,7 +22,7 @@ namespace AyaNova.Util //Diagnostic static values used during development, may not be related to config at all, this is just a convenient class to put them in #if (DEBUG) - internal static List LocaleKeysRequested { get; set; } + internal static List TranslationKeysRequested { get; set; } #endif @@ -31,9 +31,9 @@ namespace AyaNova.Util internal static string AYANOVA_CONTENT_ROOT_PATH { get; set; } //Note: set in startup.cs, not in program.cs as it requires startup IHostingEnvironment - //LANGUAGE / LOCALE - internal static string AYANOVA_DEFAULT_LANGUAGE { get; set; } - internal static long AYANOVA_DEFAULT_LANGUAGE_ID { get; set; } //internal setting set at boot by LocaleBiz::ValidateLocales + //LANGUAGE / Translation + internal static string AYANOVA_DEFAULT_TRANSLATION { get; set; } + internal static long AYANOVA_DEFAULT_TRANSLATION_ID { get; set; } //internal setting set at boot by TranslationBiz::ValidateTranslations //API internal static string AYANOVA_JWT_SECRET { get; set; } @@ -73,7 +73,7 @@ namespace AyaNova.Util { #if (DEBUG) - LocaleKeysRequested = new List(); + TranslationKeysRequested = new List(); #endif bool? bTemp = null; @@ -81,33 +81,33 @@ namespace AyaNova.Util #region SERVER BASICS //LANGUAGE - //LocaleBiz will validate this later at boot pfc and ensure a sane default is set (English) - AYANOVA_DEFAULT_LANGUAGE = config.GetValue("AYANOVA_DEFAULT_LANGUAGE"); - AYANOVA_DEFAULT_LANGUAGE = string.IsNullOrWhiteSpace(AYANOVA_DEFAULT_LANGUAGE) ? "en" : AYANOVA_DEFAULT_LANGUAGE; - string lowLocale = AYANOVA_DEFAULT_LANGUAGE.ToLowerInvariant(); - switch (lowLocale) + //TranslationBiz will validate this later at boot pfc and ensure a sane default is set (English) + AYANOVA_DEFAULT_TRANSLATION = config.GetValue("AYANOVA_DEFAULT_TRANSLATION"); + AYANOVA_DEFAULT_TRANSLATION = string.IsNullOrWhiteSpace(AYANOVA_DEFAULT_TRANSLATION) ? "en" : AYANOVA_DEFAULT_TRANSLATION; + string lowTranslation = AYANOVA_DEFAULT_TRANSLATION.ToLowerInvariant(); + switch (lowTranslation) { case "en": case "english": - AYANOVA_DEFAULT_LANGUAGE = "en"; + AYANOVA_DEFAULT_TRANSLATION = "en"; break; case "de": case "deutsch": case "german": - AYANOVA_DEFAULT_LANGUAGE = "de"; + AYANOVA_DEFAULT_TRANSLATION = "de"; break; case "es": case "español": case "spanish": - AYANOVA_DEFAULT_LANGUAGE = "es"; + AYANOVA_DEFAULT_TRANSLATION = "es"; break; case "fr": case "français": case "french": - AYANOVA_DEFAULT_LANGUAGE = "fr"; + AYANOVA_DEFAULT_TRANSLATION = "fr"; break; default: - AYANOVA_DEFAULT_LANGUAGE = "en"; + AYANOVA_DEFAULT_TRANSLATION = "en"; break; } diff --git a/startserver.bat b/startserver.bat index 53ab1d8f..2f0bc02d 100644 --- a/startserver.bat +++ b/startserver.bat @@ -1 +1 @@ -dotnet run -p ./server/AyaNova -- --AYANOVA_DB_CONNECTION="Server=localhost;Username=postgres;Password=raven;Database=AyaNova;" --AYANOVA_LOG_LEVEL="Info" --AYANOVA_DEFAULT_LANGUAGE="en" --AYANOVA_USE_URLS="http://*:7575;" --AYANOVA_FOLDER_USER_FILES="c:\temp\RavenTestData\userfiles" --AYANOVA_FOLDER_BACKUP_FILES="c:\temp\RavenTestData\backupfiles" \ No newline at end of file +dotnet run -p ./server/AyaNova -- --AYANOVA_DB_CONNECTION="Server=localhost;Username=postgres;Password=raven;Database=AyaNova;" --AYANOVA_LOG_LEVEL="Info" --AYANOVA_DEFAULT_TRANSLATION="en" --AYANOVA_USE_URLS="http://*:7575;" --AYANOVA_FOLDER_USER_FILES="c:\temp\RavenTestData\userfiles" --AYANOVA_FOLDER_BACKUP_FILES="c:\temp\RavenTestData\backupfiles" \ No newline at end of file