Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / pas2js / 2019-08

resourcestrings structure

10 messages · 2 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

warleyalex

Creating my own alternative mechanism, of course, to translations strings. Just curious, I can't find a way to generate similar JSON structure when using resourcestrings.

var resources = {
'en_GB': {
translation: {
'menu': {
'Good bye': 'Good bye! $t(menu.country)',
'Hello': 'Hello! $t(menu.country)',
'Selectyourlanguage': 'Select your language: $t(menu.country)', 'country': 'England'
}
}
},
'fr_FR': {
translation: {
'menu': {
'Good bye': 'Au revoir ! $t(menu.country)',
'Hello': 'Bonjour ! $t(menu.country)',
'Selectyourlanguage': 'Sélectionner votre langage: $t(menu.country)',
'country': 'France'
}
}
},
'it_IT': {
translation: {
'menu': {
'Good bye': 'Arrivederci! $t(menu.country)',
'Hello': 'Buongiorno! $t(menu.country)',
'Selectyourlanguage': 'Seleziona la tua lingua: $t(menu.country)', 'country': 'Italy'
}
}
},
'br_BR': {
translation: {
'menu': {
'Good bye': 'Oi! $t(menu.country)',
'Hello': 'Olá! $t(menu.country)',
'Selectyourlanguage': 'Selecione seu idioma: $t(menu.country)', 'country': 'Brasil'
}
}
}
};

Reply by email

Michael Van Canneyt
to warleyalex
warleyalex wrote
Creating my own alternative mechanism, of course, to translations strings. Just curious, I can't find a way to generate similar JSON structure when using resourcestrings.

What is your question ?

The compiler creates the internal structure. You must follow this structure when translating. How you get your translations, is entirely up to you.

I can say that when creating the "default" translation mechanism, I did not use the structure you are displaying below, because I think it makes no sense to have all languages loaded at the same time, it is a waste of memory.

Michael.

Show quoted text 53 lines
var resources = { 'en_GB': { translation: { 'menu': { 'Good bye': 'Good bye! $t(menu.country)', 'Hello': 'Hello! $t(menu.country)', 'Selectyourlanguage': 'Select your language: $t(menu.country)', 'country': 'England' } } }, 'fr_FR': { translation: { 'menu': { 'Good bye': 'Au revoir ! $t(menu.country)', 'Hello': 'Bonjour ! $t(menu.country)', 'Selectyourlanguage': 'Sélectionner votre langage: $t(menu.country)', 'country': 'France' } } }, 'it_IT': { translation: { 'menu': { 'Good bye': 'Arrivederci! $t(menu.country)', 'Hello': 'Buongiorno! $t(menu.country)', 'Selectyourlanguage': 'Seleziona la tua lingua: $t(menu.country)', 'country': 'Italy' } } }, 'br_BR': { translation: { 'menu': { 'Good bye': 'Oi! $t(menu.country)', 'Hello': 'Olá! $t(menu.country)', 'Selectyourlanguage': 'Selecione seu idioma: $t(menu.country)', 'country': 'Brasil' } } } }; -- Sent from: http://pas2js.38893.n8.nabble.com/ _______________________________________________ Pas2js maillist - https://lists.freepascal.org/cgi-bin/mailman/listinfo/pas2js

Reply by email

warleyalex
to Michael Van Canneyt

Basically i18next, looks for the attribute "data-i18n" and replaces the texts in one go using DOM manipulations.

see in action:

https://pas2js.github.io/index.html

Yeash, so the experiment is basically
I'm trying to play with pas2js "resourcestrings" with the external lib "i18next" to build multi-lingual using DOM Manipulating.

The idea is to keep a series of "language" local JSON files separared, we need to generate these files:
- en.jrs
- fr.jrs
- it.jrs
- br.jrs

Based on the units:
---------------------
unit en;

{$mode objfpc}
interface
resourcestring
  Good_bye = 'Good bye! $t(menu.country)';
  Hello =  'Hello! $t(menu.country)';
  Selectyourlanguage =  'Select your language: $t(menu.country)';
  country = 'England';
implementation
end.
-----------------------
unit fr;
{$mode objfpc}
interface
resourcestring
  Good_bye = 'Au revoir ! $t(menu.country)';
  Hello =  'Bonjour ! $t(menu.country)';
  Selectyourlanguage =  'Sélectionner votre langage: $t(menu.country)';
  country = 'France';
implementation
end.
-----------------------
unit it;
{$mode objfpc}
interface
resourcestring
  Good_bye = 'Arrivederci! $t(menu.country)';
  Hello =  'Buongiorno! $t(menu.country)';
  Selectyourlanguage =  'Seleziona la tua lingua: $t(menu.country)';
  country = 'Italy';
implementation
end.
-----------------------
unit br;
{$mode objfpc}
interface
resourcestring
  Good_bye = 'Oi! $t(menu.country)';
  Hello =  'Olá! $t(menu.country)';
  Selectyourlanguage =  'Selecione seu idioma: $t(menu.country)';
  country = 'Brasil';
implementation

end.
*****************************
... so we've generated 4 files:

pas2js -Jrunit en.pas -B
pas2js -Jrunit fr.pas -B
pas2js -Jrunit it.pas -B
pas2js -Jrunit br.pas -B

**********************************
{
"it" : {
"Good_bye" : "Arrivederci! $t(menu.country)",
"Hello" : "Buongiorno! $t(menu.country)",
"Selectyourlanguage" : "Seleziona la tua lingua: $t(menu.country)", "country" : "Italy"
}
}
------
{
"fr" : {
"Good_bye" : "Au revoir ! $t(menu.country)",
"Hello" : "Bonjour ! $t(menu.country)",
"Selectyourlanguage" : "Sélectionner votre langage: $t(menu.country)", "country" : "France"
}
}
-------
{
"en" : {
"Good_bye" : "Good bye! $t(menu.country)",
"Hello" : "Hello! $t(menu.country)",
"Selectyourlanguage" : "Select your language: $t(menu.country)", "country" : "England"
}
}
------
{
"br" : {
"Good_bye" : "Oi! $t(menu.country)",
"Hello" : "Olá! $t(menu.country)",
"Selectyourlanguage" : "Selecione seu idioma: $t(menu.country)", "country" : "Brasil"
}
}
------
*****
pas2js declares for each of the .jrs an object which is basically the namespace "unit Name", following this structure:

{
%unitName% : {
%key% : %value%,
}
}

However, we can not play i18next lib with pas2js/resourcestrings to perform multi-lingual idea.

it works as expected if we change manually all the 4 .jrs files and change the object/namespace to have multi-lingual feature.

{ filename: en.jrs }

{
"menu" : {
"Good_bye" : "Good bye! $t(menu.country)",
"Hello" : "Hello! $t(menu.country)",
"Selectyourlanguage" : "Select your language: $t(menu.country)", "country" : "England"
}
}

ahm, the command line to set manually the namespace, I think:

pas2js -Jrunit en.pas -B -NS"menu"
pas2js -Jrunit fr.pas -B -NS"menu"
pas2js -Jrunit it.pas -B -NS"menu"
pas2js -Jrunit br.pas -B -NS"menu"

Yeah, I agree: "the pas2js compiler creates the internal structure. You must follow this structure when
translating. How you get your translations, is entirely up to you."

Reply by email

warleyalex
to warleyalex: Creating my own alternative mechanism, of course, to translations strings. Just curious,…

DWscript translates resourcestring using another approach: All resource strings get an index are stored in a global JS-side array named "$R". Each time they are accessed, it is through a "$R[index]". This approach have the pros and cons, it has less overhead but if if you wish to switch language :(

---------------------------
{ filename: res.pas }

unit res;
uses Classes;
interface
resourcestring
  SInvalidFormat = '"Invalid format specifier : %s';
  SDuplicateName =  'Duplicate component name: %s';
implementation
end.
(...)
====================
begin
  console.log( SInvalidFormat );
  console.log( SDuplicateName );
end;
***************************************

JS output:

var $R =
["Missing argument in format %s",
"Invalid format specifier : %s",
"Invalid argument index in format: %s",
"List capacity (%s) exceeded.",
"List count (%s) out of bounds.",
"List index (%s) out of bounds",
"Operation not allowed on sorted list",
"String list does not allow duplicates",
"Cannot use find on unsorted list",
"Invalid component name: %s",
"%s is not a valid boolean.",
"Duplicate component name: %s",
"Invalid date: %s",
"Invalid time format: %s",
"Invalid date format: %s",
"Cannot read property %s",
"Cannot write property %s",
"Unknown property: %s",
"Indexed property %s needs parameters",
"Invalid class typecast",
"Invalid integer value: %s",
"Invalid floating-point value: %s",
"Invalid date-time value: %s",
"Invalid currency value: %s",
"%d is not a valid day of the week",
"Invalid date/timestamp : %s",
"%d %d %d is not a valid dateweek",
"Year %d does not have a day number %d",
"Year %d, month %d, Week %d and day %d is not a valid date.", "Year %d Month %d NDow %d DOW %d is not a valid date", "%f Julian cannot be represented as a DateTime",
"%d:%d:%d.%d is not a valid time specification",
"%s is not a valid GUID value",
"Illegal Nil stream for TReader constructor",
"Invalid value for property",
"Invalid stream format",
"Unknown property: %s",
"Unknown property type %d",
"Ancestor class for %s not found.",
"Unsupported property variant type %d",
"Error reading %s%s%s: %s",
"Invalid property path",
"Property is read-only",
"Class %s not found",
"Illegal Nil stream for TWriter constructor",
"Invalid property type from streamed property: %d", "Wrong token type: %s expected",
"Invalid floating point number: %s",
"Invalid integer number: %s",
"Unterminated string",
"Wrong token type: %s expected but %s found",
"Wrong token symbol: %s expected but %s found",
" (at %d,%d, stream offset %.8x)",
"Unterminated byte value",
"Invalid property",
"Seek is not implemented for class %s",
"Stream reading is not implemented for class %s",
"Stream writing is not implemented for class %s",
"Could not read data from stream",
"Could not write data to stream",
"Could not allocate memory",

    "Invalid Stream size"];
(...)
console.log( $R[1] ); // for the key SInvalidFormat
console.log( $R[11] ); // for the key SDuplicateName

Reply by email

Michael Van Canneyt
to warleyalex

That approach only works for when you compile a complete program because the resource string index is a global hardcoded index. It also means the index for a given resource string changes with every compiled program, which is simply bad design.

We have an approach that allows to load units on the fly. (dynamic packages?) It also means you can translate all strings once: you know them by name and can keep a translation file which will work accross programs.

The concept has been weighed and thought through, and is not likely to change.

Michael.

warleyalex wrote 111 lines
DWscript translates resourcestring using another approach: All resource strings get an index are stored in a global JS-side array named "$R". Each time they are accessed, it is through a "$R[index]". This approach have the pros and cons, it has less overhead but if if you wish to switch language :( --------------------------- { filename: res.pas } unit res; uses Classes; interface resourcestring SInvalidFormat = '"Invalid format specifier : %s'; SDuplicateName = 'Duplicate component name: %s'; implementation end. (...) ==================== begin console.log( SInvalidFormat ); console.log( SDuplicateName ); end; *************************************** JS output: var $R = ["Missing argument in format %s", "Invalid format specifier : %s", "Invalid argument index in format: %s", "List capacity (%s) exceeded.", "List count (%s) out of bounds.", "List index (%s) out of bounds", "Operation not allowed on sorted list", "String list does not allow duplicates", "Cannot use find on unsorted list", "Invalid component name: %s", "%s is not a valid boolean.", "Duplicate component name: %s", "Invalid date: %s", "Invalid time format: %s", "Invalid date format: %s", "Cannot read property %s", "Cannot write property %s", "Unknown property: %s", "Indexed property %s needs parameters", "Invalid class typecast", "Invalid integer value: %s", "Invalid floating-point value: %s", "Invalid date-time value: %s", "Invalid currency value: %s", "%d is not a valid day of the week", "Invalid date/timestamp : %s", "%d %d %d is not a valid dateweek", "Year %d does not have a day number %d", "Year %d, month %d, Week %d and day %d is not a valid date.", "Year %d Month %d NDow %d DOW %d is not a valid date", "%f Julian cannot be represented as a DateTime", "%d:%d:%d.%d is not a valid time specification", "%s is not a valid GUID value", "Illegal Nil stream for TReader constructor", "Invalid value for property", "Invalid stream format", "Unknown property: %s", "Unknown property type %d", "Ancestor class for %s not found.", "Unsupported property variant type %d", "Error reading %s%s%s: %s", "Invalid property path", "Property is read-only", "Class %s not found", "Illegal Nil stream for TWriter constructor", "Invalid property type from streamed property: %d", "Wrong token type: %s expected", "Invalid floating point number: %s", "Invalid integer number: %s", "Unterminated string", "Wrong token type: %s expected but %s found", "Wrong token symbol: %s expected but %s found", " (at %d,%d, stream offset %.8x)", "Unterminated byte value", "Invalid property", "Seek is not implemented for class %s", "Stream reading is not implemented for class %s", "Stream writing is not implemented for class %s", "Could not read data from stream", "Could not write data to stream", "Could not allocate memory", "Invalid Stream size"]; (...) console.log( $R[1] ); // for the key SInvalidFormat console.log( $R[11] ); // for the key SDuplicateName -- Sent from: http://pas2js.38893.n8.nabble.com/ _______________________________________________ Pas2js maillist - https://lists.freepascal.org/cgi-bin/mailman/listinfo/pas2js

Reply by email