An interesting Google Spreadsheet problem, I have a language file based on key=value that I have copied into a spreadsheet, eg.
titleMessage=Welcome to My Website
youAreLoggedIn=Hello #{user.name} you are now logged in
facebookPublish=Facebook Publishing
I have managed to split the key / value into two columns, and then translate the value column, and re-join it with the keys and Voila! this gives me a translated language file back
But as you may have spotted there are some variable in there (eg. #{user.name}) which are injected by my application, obviously I dont want to translate them.
So here is my question, given the following cell contents...
Hello #{user.name} you are now logged in
Is there a function that will translate the contents using the TRANSLATE function, but ignore anything inside #{ } (this could be at any point in the sentance)
Any Google Spreadsheet guru's have a solution for me?
Many thanks
If there are at most one occurrence of #{} then you could use the SPLIT function to divide the string into three parts that are arranged as below.
A B C D E
Original =SPLIT(An, "#{}") First piece Tag Rest of string
Translate Keep as is Translate
Put the pieces together with CONCATENATE.
=CONCATINATE(Cn,Dn,En)
I come up with same question.
Assume the escape pattern is #{sth.sth}(in regex as #{[\w.]+}). Replace them with string which Google Translate would view as untranslatable term, like VAR.
After translation, replace the term with original pattern.
Here is how I did this in script editor of spreadsheet:
function myTranslate(text, source_language, target_language) {
if(text.toString()) {
var str = text.toString();
var regex = /#{[\w.]+}/g; // g flag for multiple matches
var replace = 'VAR'; // Replace #{variable} to prevent from translation
var vars = str.match(regex).reverse(); // original patterns
str = str.replace(regex, replace);
str = LanguageApp.translate(str, source_language, target_language);
var ret = '';
for (var idx = str.search(replace); idx; idx = str.search(replace)) {
ret += str.slice(0, idx) + vars.pop();
str = str.slice(idx+replace.length);
}
return ret;
}
return null;
}
You can't just split and concatenate, because different languages use different word order of subject/predicate/object etc., and also because several languages modify nouns with different prefixes/suffixes/spelling changes depending on what they are doing in the sentence. It's all very complicated. Google needs to enable some sort of enclosing parentheses around any term we want to be quoted rather than translated.
Related
I'm trying to generate an array of values between A and B, but not finding any easy functions to do so.
GenerateArray(1,5) -> {1,2,3,4,5}
B1=8
B2=11
GenerateArray(B1,B2) -> {8,9,10,11}
Any help would be appreciated. Thanks!
All you need is the sequence function.
=SEQUENCE(B2-B1+1,1,B1,1)
B2-B1+1 will give you the number of rows needed.
https://support.google.com/docs/answer/9368244?hl=en
There is no specific spreadsheet function for that, but you can use Custom Functions.
This does involve some JavaScript and Apps Script, so you may want to look at the tutorials if you want to learn more about it.
Your example
In your Spreadsheet, open the script editor.
Paste this code:
function GenerateArray(a, b) {
// Using a simple JavaScript array to build the output
let output = [];
// For loop to go through all the numbers adding them to the output
for (let i = a; i <= b; i++){
output.push(i)
}
// Building the output as a string to add the curly brackets
output = "{" + output.toString() + "}"
// Returning final output
return output
}
Save the script.
Run it as if it was a normal spreadsheet function.
This is what it looks like in action:
Note that the function does not return a JavaScript array, which are denoted by square brackets. It returns a plain text "string". If you returned a JavaScript array from the function instead of a string, then the result would expand into adjacent columns.
So if you deleted this line:
output = "{" + output.toString() + "}"
The result you would get would be:
Yet for that you might just be better off using the SEQUENCE formula:
=SEQUENCE(1, 10)
Equivalent with native spreadsheet functions
="{" & JOIN(",",SEQUENCE(1,10)) & "}"
This will do the same as the custom function above but only using native spreadsheet functions. It makes use of JOIN to string together numbers from SEQUENCE with a comma in between them (though you can change this), and then concatenates curly braces on it with the & operator.
References and Further Reading
Spreadsheet Custom Functions
Apps Script Tutorials
For Loop
toString()
SEQUENCE
JOIN
Hello im a newbie in Lua i just want to know if there is a way to get key and value of table not using pairs,ipairs,next or other iterators? thanks in advance.!
I don't believe this is possible, as you've phrased your question in such a way that implies that the key is unknown. The only way to check for a certain value and its corresponding key would be to iterate through the whole table.
However, maybe I misunderstood and you want to get a certain value from a key without iterating through the whole table.
Say you have a table named morse as follows:
morse = { a = ".-"; b = "-..."; } -- And so on
If you wanted to convert a single character to morse you could do as follows:
morse["a"] --Which will return the string ".-"
You can do the opposite, and define a table with all the morse values and their corresponding letters like below. Note the use of square brackets to 'escape' the characters.
morse = { [".-"] = "a"; ["-..."] = "b" }
morse[".-"] -- This will return "a"
Based on your comment, I think you are looking for a string substitution using a mapping table. I think you can use string.gsub here (if your teacher still insists that .gsub is an iterator; you can ask them politely that you are unaware of the method they claim and would be delighted to actually learn about the same):
local str = "sos sos sos"
local morse = {s = "...", o = "---"}
print( str:gsub("%a", morse) )
kinda stumped with the split function, was wondering if someone can help me out.
I have a list of addresses where I'm trying to split the number and street name. These addresses have hypens in them so for example.
10-09 Main St
So i used =SPLIT(A1, " ") <- Column A has all the addresses.
The result i get is = 43017 Main St
I could use the menu tab Data >> Split text to columns but I'm trying to automate it using a script. Is there a way to force the split function to treat the data as text and not as a number?
Thank you in advance
This will work with these two user defined functions. Assuming your address is in A1.
function nbr(range) {
var addr = range.split(" ");
return addr[0];// just the nbr
}
function street(range) {
var addr = range.split(" ");
var array=[]
for(var i=1;i<addr.length;i++){
array.push(addr[i]) //create an array of split addr starting with second element
}
return array.toString().replace(/,/g," ")// convert array to string and replace all commas with soaces
}
In B1 put =nbr(A1) and in C1 put =street(A1)
Have you tried changing the column types to flat text? I was more-or-less able to replicate the behaviour when I set the column type to number, but when I changed the type to flat text, it behaved as expected.
Try Layout -> Number -> Flat text.
(Since I'm Dutch, the options might be named slightly different - apologies for that)
Already know how to show specific character.
table {"abc"}
return string.sub(table[1], 2, 2)
b
But want to replace 1 specific character inside the table without changing whole string.
table = {"abc"}
to
table = {"axc"}
In Lua, strings are strictly immutable, so they cannot be changed, per se.
As such, the only way to accomplish this is to create a new string with the content you want and insert it in table[1]. Whether or not the string is inside a table does not matter.
This would be accomplished, for example, by taking the beginning and end of the string and concatenating them with the new part:
local index = 2 -- The character we want to change
table[1] = string.sub(table[1], 1, index - 1) .. "x" .. string.sub(table[1], index + 1, -1)
This would extract all characters from the beginning of the string until the character before the one we wish to "replace", append the new character, then append the rest of the old string not including the character we "replaced".
In most cases, however, it is not very well-advised to play with single characters like this, as Lua has reasonably powerful pattern-matching and replacement facilities such as string.gsub, which allows you to replace even more complex substrings with ease. (Usage example from Programming in Lua available here)
I am new at language processing and I want to create a parser with Irony for a following syntax:
name1:value1 name2:value2 name3:value ...
where name1 is the name of an xml element and value is the value of the element which can also include spaces.
I have tried to modify included samples like this:
public TestGrammar()
{
var name = CreateTerm("name");
var value = new IdentifierTerminal("value");
var queries = new NonTerminal("queries");
var query = new NonTerminal("query");
queries.Rule = MakePlusRule(queries, null, query);
query.Rule = name + ":" + value;
Root = queries;
}
private IdentifierTerminal CreateTerm(string name)
{
IdentifierTerminal term = new IdentifierTerminal(name, "!##$%^*_'.?-", "!##$%^*_'.?0123456789");
term.CharCategories.AddRange(new[]
{
UnicodeCategory.UppercaseLetter, //Ul
UnicodeCategory.LowercaseLetter, //Ll
UnicodeCategory.TitlecaseLetter, //Lt
UnicodeCategory.ModifierLetter, //Lm
UnicodeCategory.OtherLetter, //Lo
UnicodeCategory.LetterNumber, //Nl
UnicodeCategory.DecimalDigitNumber, //Nd
UnicodeCategory.ConnectorPunctuation, //Pc
UnicodeCategory.SpacingCombiningMark, //Mc
UnicodeCategory.NonSpacingMark, //Mn
UnicodeCategory.Format //Cf
});
//StartCharCategories are the same
term.StartCharCategories.AddRange(term.CharCategories);
return term;
}
but this doesn't work if the values include spaces. Can this be done (using Irony) without modifying the syntax (like adding quotes around values)?
Many thanks!
If newlines were included between key-value pairs, it would be easily achievable. I have no knowledge of "Irony", but my initial feeling is that almost no parser/lexer generator is going to deal with this given only a naive grammar description. This requires essentially unbounded lookahead.
Conceptually (because I know nothing about this product), here's how I would do it:
Tokenise based on spaces and colons (i.e. every continguous sequence of characters that isn't a space or a colon is an "identifier" token of some sort).
You then need to make it such that every "sentence" is described from colon-to-colon:
sentence = identifier_list
| : identifier_list identifier : sentence
That's not enough to make it work, but you get the idea at least, I hope. You would need to be very careful to distinguish an identifier_list from a single identifier such that they could be parsed unambiguously. Similarly, if your tool allows you to define precedence and associativity, you might be able to get away with making ":" bind very tightly to the left, such that your grammar is simply:
sentence = identifier : identifier_list
And the behaviour of that needs to be (identifier :) identifier_list.