Copy link to clipboard
Copied
Recently I wrote a script to deal with typographic interpunction glyphs. At some point I got confused:
I've set the doubleQuotes property of one particular language (Deutsch: 2006 Rechtschreibreform) once in the app without any open document (language.id == 61)
app.languagesWithVendors.itemByID(61).doubleQuotes
→ „“
Then I opened a document and applied different glyphs for this (»«). When I now type quotes into the first paragraph, they are replaced by these glyphs.
The glyph setting in the document results in a new language id of 66:
document.languages.everyItem().id
→ 66
document.languages.itemByID(66).doubleQuotes
→ »«
So far, everything is as expected. But when I inspect the language properties of the first paragraph, I get the setting from the app itself, although this does obviously not apply when typing.
document.textFrames.firstItem().paragraphs.firstItem().appliedLanguage.id
→ 61
document.textFrames.firstItem().paragraphs.firstItem().appliedLanguage.doubleQuotes
→ „“
Copy link to clipboard
Copied
This I don't understand:
> The glyph setting in the document results in a new language id of 66:
Changing the quotes to different characters shouldn't add any languages.
And this, too, is unclear to me:
document.languages.everyItem().id
→ 66
When I do this, an array is returned that contains the IDs of all installed languages (60, in my case).
What do the following statements return at your end?
app.languageWithVendors.length
app.documents[0].languageWithVendors.length
P.
Copy link to clipboard
Copied
When I change the glyph setting in the language, while a document is opened, then I find that this affected language is saved in the document's list of languages (document.languages) and has another id (66) than the original language, that I find in app.languageWithVendors, has (61).
Copy link to clipboard
Copied
document.languages.everyItem()
only gives me the one language where I have made a setting, not all installed languages.
Copy link to clipboard
Copied
> document.languages.everyItem()
> only gives me the one language where I have made a setting, not all installed languages.
Strange, I don't see that over here in (my UK-English) InDesign.
But what you describe towards the end of your original mail ("But when I inspect the language properties of the first paragraph, I get the setting from the app itself . . .") I can reproduce, and looks like a bug.
Copy link to clipboard
Copied
Yes, I agree, but wasn't shure if I understand InDesign correctly, here. In my script I wanted to process text according to the language settings in the document itself. Since for each paragraph I need to look up the applied language, it woud be easy to look for it's settings right there. Instead, I needed to search in document.languages for a language with the same name and use those settings.
Copy link to clipboard
Copied
Hi @haukeh96518267 , You might want to loop throught the document languages to make sure you have the right ID, I think the app IDs are going to be different than the doc IDs. Also the doubleQuotes property refers to the glyph that will be used when typographersQuotes is set to true—it wont affect existing quotes. This sets the first paragraph to German: 2006 Reform—114 in my document. After running the script try typing ":
var doc = app.activeDocument
var lang = doc.languages;
/* for (var i = 0; i < lang.length; i++){
$.writeln(lang[i].name + " "+lang[i].id)
}; */
//German: 2006 Reform 114
var gr = lang.itemByID(114);
//the doubleQuotes property refers to the glyph used when the typographers quote prefs are turned on
//it wont affect existing quotes
gr.doubleQuotes = "»«"
doc.textPreferences.typographersQuotes = true;
doc.textFrames.firstItem().paragraphs.firstItem().appliedLanguage = gr;
Copy link to clipboard
Copied
Also, looks like you can use itemByName, but it’s looking for the untranslated name for German: 2006 Reform—"de_DE_2006". This might be better:
var lang = app.languagesWithVendors;
/* for (var i = 0; i < lang.length; i++){
$.writeln(lang[i].name + " "+lang[i].untranslatedName)
}; */
var gr = lang.itemByName("de_DE_2006");
gr.doubleQuotes = "»«"
var doc = app.activeDocument;
doc.textPreferences.typographersQuotes = true;
doc.textFrames.firstItem().paragraphs.firstItem().appliedLanguage = gr;
After running the script typing " " gives me this:
Copy link to clipboard
Copied
Thanks for suggestions. My script works similar, and does already work fine. I just posted here to better understand the behaviour with the language properties inside the paragraph object. Like Peter, I believe it to be a bug and if so, I's like to report it.
As you already mentioned, itemByName is fiddly with the languages and can basically only be used for specific languages where the internal name is known. When dealing with arbitrary names, one needs to find the internal name using app.findKeyStrings(), but then that doesn't work directly, the key has to be edited somehow. At that point, I gave up and just wrote my own findByName function.
Copy link to clipboard
Copied
basically only be used for specific languages where the internal name is known
It’s looking for .untranslatedName not .name (which is listed in the Character panel).
This gets the .name and .untranslatedName properties:
var lang = app.languagesWithVendors;
for (var i = 0; i < lang.length; i++){
$.writeln(lang[i].name + " >> "+lang[i].untranslatedName)
/* returns:
[No Language] >> [No Language]
Bengali (India) >> bn_IN
Gujarati (India) >> gu_IN
Hindi (India) >> hi_IN
Kannada (India) >> kn_IN
Malayalam (India) >> ml_IN
Marathi (India) >> mr_IN
Oriya (India) >> or_IN
Punjabi (India) >> pa_IN
Tamil (India) >> ta_IN
Telugu (India) >> te_IN
Bulgarian >> Bulgarian
Catalan >> Catalan
Czech >> Czech
Danish >> Danish
German: Swiss >> German: Swiss
German: Swiss 2006 Reform >> de_CH_2006
German: 1996 Reform >> German: Reformed
German: 2006 Reform >> de_DE_2006
Greek >> Greek
English: Canadian >> English: Canadian
English: UK >> English: UK
English: USA >> English: USA
English: USA Medical >> English: USA Medical
Spanish >> Spanish: Castilian
Estonian >> Estonian
Finnish >> Finnish
French: Canadian >> French: Canadian
French >> French
Croatian >> Croatian
Hungarian >> Hungarian
Italian >> Italian
Lithuanian >> Lithuanian
Latvian >> Latvian
Norwegian: Bokmål >> Norwegian: Bokmal
Dutch: Old Rules >> Dutch
Dutch: 2005 Reform >> nl_NL_2005
Norwegian: Nynorsk >> Norwegian: Nynorsk
Polish >> Polish
Portuguese: Brazilian >> Portuguese: Brazilian
Portuguese: Orthographic Agreement >> Portuguese: Orthographic Agreement
Portuguese >> Portuguese
Romanian >> Romanian
Russian >> Russian
Slovak >> Slovak
Slovenian >> Slovenian
Swedish >> Swedish
Turkish >> Turkish
Ukrainian >> Ukrainian
English: USA Legal >> English: USA Legal
German: Old Rules >> German: Traditional
Hebrew >> Hebrew
Arabic >> Arabic
German: Austria 2006 Reform >> German: Austrian
Indonesian (Indonesia) >> id_ID
Khmer (Cambodia) >> km_KH
Lao (Laos) >> lo_LA
Burmese (Myanmar [Burma]) >> my_MM
Sinhala (Sri Lanka) >> si_LK
Thai >> Thai */
};
Not sure I’m seeing the problem. When I run my script and type "" (not the Option - [ keyboard command for a typographic quote), I get the expected «» glyphs.
You have to have Preferences> Type >Use Typographer’s Quotes checked, and then type an inch mark when you want to set the «» marks.
Copy link to clipboard
Copied
Thanks for the hint about untranslatedName. I had tried app.findKeyStrings(), but that gives another name which is not found by languages.itemByName().
The problem is not that typing would work in an unexpected way, but using paragraphs.firstItem().appliedLanguage.doubleQuotes does not, resp. gives other glyphs than configured for the document. Since my script does the typing for me, it gave wrong glyphs in the first attempt. As described above, I have found a workaround, but still believe that Paragraph.appliedLanguage gives a wrong result. The returned language object has the properties as configured for the application, but not for the document.
Copy link to clipboard
Copied
Appologies if I’m missing somthing. A document has a collection of languages, but not an .appliedLanguage property—.appliedLanguage is a character or text property—you could have different languages applied to the words within a single paragraph.
Here my gr variable returns German: 2006 Reform as its name as expected, and the first paragraph’s appliedLanguage name returns the same. If I try to get the document’s appliedlanguage, I get an error.
var lang = app.languagesWithVendors;
var gr = lang.itemByName("de_DE_2006");
gr.doubleQuotes = "»«";
gr.singleQuotes = "‹›"
$.writeln(gr.name) //returns German: 2006 Reform
var doc = app.activeDocument;
doc.textPreferences.typographersQuotes = true;
var p1 = doc.textFrames.firstItem().paragraphs.firstItem();
p1.appliedLanguage = gr;
$.writeln(p1.appliedLanguage.name) //returns German: 2006 Reform
$.writeln(doc.appliedLanguage.name) //returns an error
Copy link to clipboard
Copied
The subject admittedly complex, please forgive me, if I'm not explaining it clearly. My script is not supposed to set language properties, but to do typograpy text editing, according to the settings in the document. Since every paragraph might have a different language setting (Paragraph.appliedLanguage), I read this and then look up the quotes which are set for this language. But when I do that in the direct way
myParagraph.appliedLanguage.doubleQuotes
then I get wrong quotes: those as set in the application, not in the document. Instead I have to look up the languages name, find that in document.languages and then get that quotes:
var langName = myParagraph.appliedLanguage.name;
var docLang = findInArray(document.languages, function(dl) {
return l.name === dl.name;
});
var quotes = docLang.doubleQuotes;
// These are the quotes that would apply if the user typed something
// and can differ from myParagraph.appliedLanguage.doubleQuotes
function findInArray(arr, cb) {
for (var i = 0; i < arr.length; ++i)
if (cb.call(this, arr[i])) return arr[i];
return undefined;
}
Off topic:
gr.doubleQuotes = "»«"; // this is used in Germany and Austria
gr.singleQuotes = "‹›" // this is used in Switzerland.
InDesign does not offer the german/austrian variant for singleQuotes--which is one of the reasons why we need a script to cope with quotes...
Copy link to clipboard
Copied
Not sure if this has been mentioned but the icuLocaleName property (an ISO string of the form xx_YY) is available since CS5 and seems to successfully pass the itemByName() method.
E.g.
var icu = 'bn_IN';
var lg = app.languagesWithVendors.itemByName(icu);
alert( lg.isValid && lg.name ); // => Bengali (India)
This doesn't answer your primary question but might help.
Best,
Marc
Copy link to clipboard
Copied
When you output an array in some environments, they will get converted to string with a routine that omits the square brackets. With a single item you also get no comma, giving the perception of an integer.
Besides, the applied language is a character attribute. The largest text entity to examine would be textStyleRun rather than paragraph (I think that only looks at the first character). You can also see the effect at the character attributes panel - when the entire paragraph is selected you might see a mixed indicator.
Also don't rely on those IDs, they are allocated consecutively first come first serve in the initial startup process (for application preferences), or when a document is created. The next version of InDesign might behave differently. This has also recently caused some problems where an IDML generator was not prepared for shifting numbers.
I'd have to look for details, but I think there are also some differences between language and language with vendor, e.g. for languages where multiple vendors provide hyphenation etc. dictionary.
Copy link to clipboard
Copied
Thanks so far. What is your adivce to look for the language property of text. Inspect textStyleRange? I had looked into the paragraph, because the language is set in the paragraph style. But you are right, this is also in the character style and thus a character property.
Copy link to clipboard
Copied
rather than paragraph (I think that only looks at the first character)
Yes, you can see that with this where the loop randomly assigns languages to each word in the paragraph:
var doc = app.activeDocument;
var lang = doc.languages;
var p1 = doc.textFrames.firstItem().paragraphs.firstItem();
var p1w = p1.words;
for (var i = 0; i < p1w.length; i++){
p1w[i].appliedLanguage = lang.anyItem()
};
//both of these return a random language
$.writeln(p1w[0].appliedLanguage.name)
$.writeln(p1w[1].appliedLanguage.name)
//paragraph returns the first character’s language when there is a mix
$.writeln(p1.appliedLanguage.name)
Also, doc.languages and app.languagesWithVendors are collections so they don’t neccessarily act like arrays
Copy link to clipboard
Copied
After several answers with interesting hints, the basic question remains open: When I do configuration for a language in a document, such as setting doubleQuotes, this language can be found in the document object's list of languages and has another id than that in the application object's list.
But when I access text inside the document – regardless what I inspect, paragraph, words, character, textStyleRange – I always get the language properties as set in the app, not in the document.
I still believe this to be a software bug.
Copy link to clipboard
Copied
" I always get the language properties as set in the app, not in the document. I still believe this to be a software bug."
Could also be a questionable design decision. If it is a bug, it is very old and I do not think, it will be fixed soon.
Nevertheless you could do a bug report at InDesign UserVoice.
As a result of this discussion the obvious workaround is to get the value of the appliedLanguage.untranslatedName of a textStyleRange and feed it as argument to doc.languages.itemByName() so you can see the right value for e.g. doubleQuotes or singleQuotes.
var doc = app.documents[0];
var textStyleRanges =
doc.stories.everyItem().textStyleRanges.everyItem().getElements();
for( var n=0; n<textStyleRanges.length; n++ )
{
var untranslatedName =
textStyleRanges[n].appliedLanguage.untranslatedName;
var doubleQuotes =
doc.languages.itemByName( untranslatedName ).doubleQuotes;
$.writeln( n +"\t"+ untranslatedName +"\t"+ doubleQuotes );
};
Thanks to Rob Day who pointed at property untranslatedName.
The code above is working without issues in my German version of InDesign 2022 on Windows 10.
Regards,
Uwe Laubender
( Adobe Community Professional )
Copy link to clipboard
Copied
Hi Uwe, I don‘t do enough language work to understand why there are two different collections, but the app’s LanguagesWithVendors is a collection of LanguageWithVendors objects, while the document’s Languages is a collection of Language objects. The Language and LanguageWithVendors objects don’t have matching properties, so it’s not surprising that they return different ids.
LanguageWithVendors has dictionaryPaths, hyphenationVendorList, spellingVendorList, and thesaurusVendor properties, which the Language object does not have
Copy link to clipboard
Copied
Hi Rob,
well, hyphenationVendor or spellingVendor is also available for language.
dictionaryPaths is not a document specific property so it makes sense to bind it with languageWithVendors in application.
To get a specific hyphenationVendor for a text style range of a document it works very well like this:
var doc = app.documents[0];
var textStyleRanges =
doc.stories.everyItem().textStyleRanges.everyItem().getElements();
for( var n=0; n<textStyleRanges.length; n++ )
{
var untranslatedName =
textStyleRanges[n].appliedLanguage.untranslatedName;
var hyphenationVendor =
doc.languages.itemByName( untranslatedName ).hyphenationVendor;
$.writeln( n +"\t"+ untranslatedName +"\t"+ hyphenationVendor );
};
/*
0 de_DE_2006 Duden
1 English: UK Hunspell
2 de_DE_2006 Duden
*/
So I get what I want in case…
Regards,
Uwe Laubender
( Adobe Community Professional )
Copy link to clipboard
Copied
Thanks, I filed a bug, let's see what happens. For now we have the workaround.
Copy link to clipboard
Copied
Voted.
Regards,
Uwe Laubender
( Adobe Community Professional )
Copy link to clipboard
Copied
Likewise.
Copy link to clipboard
Copied
Just a note, also to myself, property untranslatedName of language and languageWithVendors was added to the DOM with InDesign 2015 version 11.
Regards,
Uwe Laubender
( Adobe Community Professional )