generating Localizable.strings creates strange output - iphone

When I use genstrings -o en.lproj *.m it generates the Localizable.strings file with entries in this structure:
/* this is the text: %# ID: %02X */
"this is the text: %# ID: %02X" = "this is the text: %1$# ID: %2$X";
Please notice that it makes from %# -> %1$#
Why is this? I always have to change it back to %# manually.
Thanks

Did you use the "-j" option? It produces java localized string (which have the format like %1$#).
[EDIT]
Sorry, looked at the wrong manual page. Please use the option -noPositionalParameters to turn off generation of positional parameters. -> Info's here

You don't need to change it back, since %1$# refers to the first argument given to your format string.
Actually, in a case different from yours, it might happen that the order of the arguments changes from a translation to another. For example, if your code uses a format to display some player property value like:
let fmt = NSLocalizedString("Player property value", comment: "The player property value")
String(format:fmt, playerName, playerProperty, value)
You might have in the "en.lproj/Localizable.strings":
/* The player property value */
"Player property value" = "Player %1$#'s %2$# is %3$d"
and in the "fr.lproj/Localizable.strings":
/* The player property value */
"Player property value" = "Le %2$# du joueur %1$# is %3$d"
or:
/* The player property value */
"Player property value" = "Le joueur %1$# a %3$d points de %2$#"

Related

How to localize title and description? (LocalizedStringResource)

I am working on my SwiftUI project and added some AppIntents for the Shortcuts app. Currently I am not able to localize the title and description. The title and the description are of type LocalizedStringResource (available from iOS16+).
I tried to localize the following code to German, but I don't know how to do it.
struct Add_Memory_Shortcut: AppIntent {
// The name of the action in Shortcuts
// TODO: Localization
static var title : LocalizedStringResource = "Create Memory"
// Description of the action in Shortcuts
// Category name allows you to group actions - shown when tapping on an app in the Shortcuts library
static var description: IntentDescription = IntentDescription("Create a new memory", categoryName: "Creating")
}
Any help or link is appreciated. Thanks :)
I tried everything, only one thing works, add your localization strings in
Localizable.strings
And if you want to localize string with paramter
//Localizable.strings
"hello_user%#" = "Hello %#";
//Your AppIntents
let welcomeMSG = LocalizedStringResource("hello_user\(userName)")
LocalizedStringResource doesn't have a ton of documentation available, but take a look at https://developer.apple.com/documentation/foundation/localizedstringresource/3988421-init:
init(
_ keyAndValue: String.LocalizationValue,
table: String? = nil,
locale: Locale = .current,
bundle: LocalizedStringResource.BundleDescription = .main,
comment: StaticString? = nil
)
For table, it says: "The name of the table containing the key-value pairs. If not provided, nil, or an empty string, this value defaults to Localizable.strings." In my experience that's not currently true, and you may need to explicitly point it to your translations, e.g.:
let myString = LocalizedStringResource("Hello, big world!", table: "Localizable.strings")
If you do that, supply appropriate translations, and set a locale that matches, you will see the localized version presented -- at least within a SwiftUI view:
Text(myString)

How to insert a placeholder in a json key:value ? Flutter

I'm porting my Swift app to Flutter and for localising it I'm following this https://github.com/billylev/flutter_localizations but I can't see how to insert placeholder to insert a value in the translated values.
Basically the guide uses
String text(String key) {
return _localisedValues[key] ?? "$key not found";
}
to get the corresponding key:value pair from a .json file as
{
"Shop": "Negozio",
}
I just pass it in the Textwidget as :
Text(AppLocalizations.instance.text('Shop')).
How to modify text to insert one or more placeholders and how would be the .json be constructed?
Say for the value "User": "User" I'd like to insert a value after the transaction I can simply use a string sum and add the value as `Text(
AppLocalizations.instance.text('User') + ' ${widget.user.name}', but if I need to insert a value in the middle of the translated sentence, eg a message, I don't see how to accomplish it.
I need it to make localised versions of incoming push notification, and they have args.
In Swift I have it like this:
"ORDER_RECEIVED_PUSH_TITLE" = "Order number: %#";
"ORDER_RECEIVED_PUSH_SUBTITLE" = "Shop: %#";
"ORDER_RECEIVED_PUSH_BODY" = "Thank you %#! We received your order and we'll let you know when we start preparing it and when it's ready. Bye";
Any suggestions on how to accomplish that in Flutter?
Many thanks
I was suggested this package https://pub.dev/packages/sprintf#-installing-tab- and it works just as I needed. Sprintf just lets you specify one or more placeholders in a String and pass an array of args.
https://developermemos.com/posts/using-sprintf-flutter-dart. for more info, even this is pretty much it. So for example
"ORDER_RECEIVED_PUSH_TITLE" = "Order number: %#";
in the .json file would be :
{
"ORDER_RECEIVED_PUSH_TITLE": "Oder number: %s"
}
and using it would be
String orderNumber = 'some uuid';
Text(Sprintf(AppLocalitazions.instance.text('ORDER_RECEIVED_PUSH_TITLE'),[orderNumber]);
Hope this helps others.

Restore String Interpolation AFTER value replace

Given a str: "My name is Gustavo", that was created with "My name is \(foo.name)"
Is it possible to get the string "My name is \(foo.name)" after the value was replaced?
In other words, is it possible to find out "My name is \(foo.name)", having "My name is Gustavo"?
Edit: If I can get to "My name is ", a.k.a. the hard coded string from all strings that were build dynamically, that would be a solution.
No, this is not possible. In fact, "My name is \(foo.name)" is not even included in the compiled code. Instead, Swift-5 compiler generates code equivalent to this:
let str = String(stringInterpolation: {
var temp = String.StringInterpolation(literalCapacity: 11, interpolationCount: 1)
temp.appendLiteral("My name is ")
temp.appendInterpolation(foo.name)
return temp
}())
This article contains details on how string interpolation is implemented in Swift-4 and Swift-5.

Fill a Word document form with OLE in C++ Builder

I want to have my C++ Builder application fill the following Word document form :
http://oesv.at/media/media_vereinsservice/media_formulare/Zuschlagsberechnung-Alpin_06-07.doc
I manage to do this with Ole procedures calling OpenOffice Writer but for users of my application who don't have OpenOffice installed but Microsoft Office instead I want to call Ole procedures with Word.
I tried without success to find and see the structure of this document file: like a tree map with : the document object, the Fields or FormFields objects, their properties "Field", which have properties Result, which is a range object having property Text and the document property Selection which has the procedure "TypeText". But no structure view available, so just guessing in the dark how the document file is structured.
Here below two solutions I tried without success:
first: the commented part consist on selecting the text input field and have this current selection in the document call its procedure "TypeText". This throws an error saying the object I try to modify is in a protected area of the document : "EOleException : Cette méthode ou propriété n'est pas disponible car l'objet fait référence à une zone protégée d'un document.".
second: the code below throws an error "EOleException : Le type ne correspond pas" that can be translated "Type mismatch" on the line "Result.OlePropertySet("Text", vInputText);". I have tried to pass a WideString or directly the default string format for my project without success.
try
{
//---ouverture de Word
vMSWord.OlePropertySet("Visible", false);
//---ouverture du fichier
vFileName = Variant(wFile.c_bstr());
vWDocuments = vMSWord.OlePropertyGet("Documents");
vWDocument = vWDocuments.OleFunction("Open", vFileName);
Variant fields, field;
fields = vWDocument.OlePropertyGet("FormFields");
for (int i=1; i<=fields.OlePropertyGet("Count"); i++)
{
Variant field = fields.OleFunction("Item",(Variant)i);
//field.OleFunction("Select");
//Variant selection = vMSWord.OlePropertyGet("Selection");
//selection.OleProcedure("TypeText",WideString("My input text"));
Variant Result = field.OlePropertyGet("Result"); // result = objet range
Variant vInputText = Variant(WideString("My input text").c_bstr());
Result.OlePropertySet("Text", vInputText);
}
//---sauvegarde en fichier texte
vFileName = Variant(wNewFile.c_bstr());
ShowMessage("Saveas :");
vWDocument.OleProcedure("Saveas", vFileName);
}
catch(Exception &e)
{
ShowMessage(AnsiString(e.ClassName())+ e.Message);
}
I do it so:
...
String FieldName = "SomeFormFieldName"; // Try WideString
String Text = "SomeText"; // Try WideString
Variant Field = Document.OlePropertyGet("FormFields").OleFunction("Item", (OleVariant)FieldName);
Field.OlePropertyGet("Range").OlePropertySet("Text", Text);
...
But you must be shure that the Document contains fields is exactly of FormFields type not MergeField or others. Also you must set the Bookmark property for Fields inside the template document and use it as FieldName.

GTK - How to update gtktextview/gtkentry? #C

i am creating a basic GROUND CONTROL STATION for a CubeSat, dividing it in two parts: COMMANDS (with no problems) and TELEMETRY. I am using C code and GTK; in the telemetry windowt I need to show some info everytime a telemetry packet is received so I've tried to use a gtkview/gtkentry for each info, but I don't know, how to update the message shown in them.
In particular, an example is:
//View PACKET NUMBER
view = gtk_text_view_new();
frame = gtk_frame_new("Packet number");
gtk_container_add(GTK_CONTAINER(frame), view);
gtk_text_view_set_editable(GTK_TEXT_VIEW(view),FALSE);
gtk_table_attach(GTK_TABLE(table2),frame,0,1,0,1,GTK_FILL,GTK_FILL,5,5);
buff = gtk_text_view_get_buffer(GTK_TEXT_VIEW(view));
gtk_text_buffer_get_iter_at_offset(buff, &iter, 0);
gtk_text_buffer_insert(buff, &iter,"waiting", -1);
so, first there is the text "WAITING", then when a packet is received I want to update that text: how can I do this?
I've tried repeating this code but changing "waiting" with a variable referring to "packet number", but I obtain core dump
I've also tried with this code, but I have always same problem.
viewprova = gtk_entry_new();
frameprova = gtk_frame_new("Packet number");
gtk_container_add(GTK_CONTAINER(frameprova), viewprova);
gtk_entry_set_editable(GTK_ENTRY(viewprova),FALSE);
gtk_table_attach(GTK_TABLE(table2),frameprova,0,1,0,1,GTK_FILL,GTK_FILL,5,5);
gtk_entry_set_text(GTK_ENTRY(viewprova),"waiting");
frameprova = gtk_frame_new("Packet number");
viewprova = gtk_label_new ("waiting");
gtk_container_add(GTK_CONTAINER(frameprova), viewprova);
gtk_table_attach(GTK_TABLE(table2),frameprova,0,1,0,1,GTK_FILL,GTK_FILL,5,5);
Thanks for the help!
A function such as gtk_label_new() that accepts a C string can't take an integer instead, C functions are not polymorphic. You need to build a string representation and pass that, for instance using snprintf() to format the number into a string buffer.
Ok, so if I understood you correctly, you know how to setup your text displaying widgets, but not, how to fill them with new contents, correct? Look at your code, and at what you're doing. First, you're creating a text widget. Then you fill it with initial text. This second part is the one you repeat:
In case of GtkEntry, gtk_entry_set_text(GTK_ENTRY(viewprova), "My new text");
In case of GtkTextView (actually you're using the underlying TextBuffer), gtk_text_buffer_set_text(buff, "My new text", -1);