Script to modify paragraph styles based on user-selected input value
Copy link to clipboard
Copied
Hi,
I'd appreciate any help with the following. First, I'll describe the problem, to estabish context and also open the door for anyone who has a better suggestion than my proposed solution.
The Problem
- I produce a large range of product documents (user guides, product inserts etc) which use a consistent set of styles. The styles are maintained in their own InDesign document. Every time I edit a document, first thing I do is re-import all the styles, to make sure it's got the latest. This is cumbersome but I don't know of any other way to keep them all in sync.
- Several paragraph stylesheets (currently: 4) have numbering styles that contain text prefixes: Appendix, Chapter, Table, and Figure. (Each has its own list style.)
- Once the English version of a document is ready, it goes to our outsourced translation service. I give them a separate copy of the English 'source document' for each target language. We currently have 4 languages other than English but that will increase over time.
- The translators have standing instructions to translate the text prefixes in those stylesheets (so 'Table' becomes 'Tabla' in Spanish). But the next time that document is modified (for any reason), I will reimport the stylesheets—thus resetting 'Tabla' to 'Table'.
Proposed Solution
- A script that contains preconfigured sets of prefixes (Appendix, Chapter, Table, and Figure) in each language. I would modify this whenever we add a language. Although I don't know InDesign scripting, I'm familiar with concepts such as variables from other scripting languages like VBA.
- When it is run, the script could pop up a dialog allowing me to choose the language. It would then use that set of prefixes to modify the relevant stylesheets.
- The proposed workflow: before sending a document for translation, I would first reimport all the styles, then run the script. The translators would receive a document with those terms already translated. The same would happen if the document needs to be modified subsequently (for example, whenever I tweak a stylesheet in my common set, I have to reimport them back into every document, though I don't do this until the next time I modify each document).
Apologies for the lengthy description but I thought it would be helpful to understand the context, especially as I can't be sure the proposed solution is the best one (or even a good one).
Cheers,
--Alistair
Copy link to clipboard
Copied
Oops! I just realized that the script would also need to modify TOC styles: [Default], Tables, and Figures.
Cheers,
--Alistair
Copy link to clipboard
Copied
This could, in some way, be made a bit easier for you if you would use Book feature - but if you work on Windows - all this and way more of your mundane clicking - can be easily automated using my ID-Tasker tool - but it's not free and Windows only.
With my tool - it could be a one-click-solution for you - first "export" for translation - then "import" - including creation of one combined file with each translation on a separate / dedicated layer - if needed - including copy of the whole Styles Structure, localised images / graphics, etc.
And by "export" I mean full service - separate folders with correctly named files, etc. - including creation of packages - File -> Package and/or ZIP / RAR archive - and - if the translation company has an FTP server - automatic upload - and then download.
And all that - just for starters 😉
And if the translation company isn't "fitting" texts - they only process IDML files without opening them in the InDesign - or you would prefer to do it "in house" - this also can be fully/semi automated - your choice.
Copy link to clipboard
Copied
One of the day-to-day tasks I perform for translation firms on a regular basis is to prepare InDesign files for translation. Similarly, I frequenly advise businesses and organizations that use external translations services on how they can improve their own translation workflows and reduce translation costs. (In other words, this isn't the first time I've seen your question.) There is a wide variety of tools that these translation providers use, and your question somewhat implies that you're imagining what being a localization engineer might be like. So, when you propose the idea that you could pre-translate parts of the document before assignment with a custom tool, in order to save yourself effort after you get the translated documents back? There is an entire world of enterprise-class tools to do exactly that. And, pardon me for being a little bit flippant here, every time your InDesign files cross the desktops of your provider's localization engineers, they're letting out a little world-weary sigh and undoing some of your preparatory work.
See, any reasonably technically proficient firm on the planet is using a tool that consumes IDML exported from InDesign. Very rarely are you going to find that your InDesign files are being opened up in InDesign by your Spanish translators. More likely, your text gets extracted and is processed (translated by humans, translated by machines, terminology controlled from client glossaries, post-translation editing, etc.) in tools that aren't graphic design tools at all.
One of my jobs, broadly speaking, is to make sure that the tool that is consuming your work can actually process all of the text, in human-readable units. So when you say
Several paragraph stylesheets (currently: 4) have numbering styles that contain text prefixes: Appendix, Chapter, Table, and Figure.
I know that your entry in my client's workflow tool or CRM module or whatever would have this fact noted, and it'd be my job to automate the process of getting terms like "Appendix" out of the paragraph style, and into the live text. Then I'd build a tool to put it back in there after transation, because the last thing I'd want to do is to have my client deliver something to you that didn't match what you'd sent. Clearly, your provider isn't doing that step, or it'd say "capítulo" in your styles in your Spanish doc where it says "chapter" in English.
So if you really wanted to make this process faster & less troublesome for everyone, you should be raising these questions directly with your provider. I don't know what tools they use, so I don't know what optimizations to your workflow would be the most likely to make it so you wouldn't have to go looking for custom tool development to preserve your tablas and your capítulos. I don't assume that you doing pre-translation with a custom tool is the best way, but it might well be, depending on business conditions. Better to go back to your provider and talk about how you need to post-process their deliveries, and if my guesses are correct, they'll come back with "Well, we need to pre-process your assignments! We're working at cross-purposes here; let's stop ."
But if you don't have that kind of relationship with your provider, two ideas spring immediately to mind:
1) One element of a paragraph style in InDesign is the language. Why don't you have a separate Spanish style template that already has your tablas and your capítulos? That means more style management work on your end, of course, but if you're working with Spanish text, it really ought to be marked as Spanish, right? And there are ways to automate away some of that style-management effort.
2) In general, I'd say live text doesn't belong in paragraph styles. I mean, where is it? In Bullets and Numbering? Edit your master styles to remove all text that you mean to have translated, and put it in the live text. That's what I'd do, in my hypothetical job as the loc engineer preprocessing your files.
Copy link to clipboard
Copied
Thanks for your detailed and considered reply. As I made clear in my original post, I'm well aware that my proposed solution may not be right, and when I invited alternative suggestions, I did so sincerely. If 45 years in production has taught me anything, it's that it's never safe to make assumptions about someone else's workflow or the reasons behind it. So, no, I am not attempting to imagine how a localization engineer works. Indeed, this wasn't about how they work at all, and I apologise if that wasn't clear. It's about how I work. But I'll come back to that later.
My working relationship with our translation service is, as far as I'm aware, open and co-operative. I certainly don't try to tell them how to do their job: I'm busy enough trying to do my own. There is no way I am going to spend even 1 minute of effort in attempting to make something easier or better for them, unless they have specifically told me it's what they want. I have provided detailed but succinct documentation on our stylesheets and made it clear that if there's anything they'd like me to do differently, my door (and more importantly, my attitude) is open. So far, the only feedback has been to say "much appreciated". I'm not aware if it was accompanied by a little world-weary sigh or not—but if it was, that's on them. You can lead a horse to water…
The purpose of my solution isn't so that I can pre-translate these prefixes. It's so that I don't lose the translations when I need to re-sync the stylesheets after they return the documents to me. If the entire document needs to be retranslated, it doesn't matter. But if I am simply changing a few stylesheets, I have no reason to send it back (and can't justify the time and expense of doing so). I just want to reimport my standard stylesheets, then run a script to change all the prefixes back to their required languages. (In my original post, I did float the idea of also running that script before I send them a document in English, but I take your point that it's unnecessary and undesirable.)
Yes, I could have separate stylesheets, or even separate style templates, for each language, but I don't see how that solves the issue. Because, for Latin, Greek and Cyrillic writing systems, all the stylesheets ultimately derive from the English: if I change a stylesheet setting in English, I still need to sync it the others, no matter where they live. And then they will lose their localization and it will have to be redone. I can (and currently do) keep a record of each prefix translated into each language; each time I reimport the stylesheets, I go through and restore all the tabelles and tabelas manually. But even with four foreign languages, it's a pain, and four will soon grow into doube figures.
As for live text, I agree with you in general. But I am using InDesign's Paragraph Style: Numbering feature because, as far as I know, that's the only way to automate the numbering. If there's another way that I can have figures, tables, chapters and appendices automatically numbered Figure 1, Figure 2, Figure 3 etc, then believe me, I'm all ears!
Thanks again.
Copy link to clipboard
Copied
Hi @Alistair36395154jraa I don't really understand your workflow—there are some things that don't make sense based on the limited info you've given us—but I'll leave that to experts like Joel.
However, aside from that, I'm a crazy scripter and this caught my interest, despite that there's a high chance it isn't what you need anyway and might not be the best way to go in any case. So here is a script that renames document styles per configured languages, with a simple UI. Read the script instructions and edit the `settings` object as needed. Will this help?
- Mark
/**
* @file Rename Styles By Language.js
*
* Replaces words in document style names from one configured
* language list of words to another and also sets the applied language.
*
* Edit the `settings` object below as needed.
*
* @author m1b
* @version 2025-03-23
* @discussion https://community.adobe.com/t5/indesign-discussions/script-to-modify-paragraph-styles-based-on-user-selected-input-value/m-p/15226562
*/
function main() {
var settings = {
/** the translation languages; add more as you need. */
languages: {
'English': { words: ['Appendix', 'Chapter', 'Figure', 'Table'], appliedLanguage: 'English: USA' },
'German': { words: ['Anhang', 'Kapitel', 'Abbildung', 'Tabelle'], appliedLanguage: 'German: 2006 Reform' },
'Spanish': { words: ['Apéndice', 'Capítulo', 'Figura', 'Tabla'], appliedLanguage: 'Spanish' },
},
/** the language to translate from */
fromLanguage: 'English',
/** the language to translate to */
toLanguage: 'Spanish',
/** which document elements to translate */
translateThese: [
'allParagraphStyles',
// 'allCharacterStyles',
// 'allObjectStyles',
// 'allCellStyles',
// 'allTableStyles',
],
/** whether to show UI */
showUI: true,
/** whether to show user how many translations were made */
showResults: false,
};
if (0 === app.documents.length)
return alert('Please open a document and try again.');
var doc = settings.doc = app.activeDocument;
// collect all the styles to rename
var styles = [];
for (var i = 0; i < settings.translateThese.length; i++) {
var things = doc[settings.translateThese[i]];
for (var j = 0; j < things.length; j++)
styles.push(things[j]);
}
if (settings.showUI) {
var result = ui(settings);
if (2 === result)
// user cancelled
return;
}
var counter = 0,
fromWords = settings.languages[settings.fromLanguage].words,
toWords = settings.languages[settings.toLanguage].words,
appliedLanguage = getThing(app.languagesWithVendors, 'name', settings.languages[settings.toLanguage].appliedLanguage);
// do the renaming
for (var i = 0; i < styles.length; i++) {
wordLoop:
for (var j = 0; j < fromWords.length; j++) {
if (-1 === styles[i].name.search(fromWords[j]))
continue wordLoop;
styles[i].name = styles[i].name.replace(fromWords[j], toWords[j]);
if (
styles[i].hasOwnProperty('appliedLanguage')
&& undefined != appliedLanguage
)
styles[i].appliedLanguage = appliedLanguage;
counter++;
}
}
if (settings.showResults)
alert('Translated ' + counter + ' style names\nfrom ' + settings.fromLanguage + ' to ' + settings.toLanguage + '.');
};
app.doScript(main, ScriptLanguage.JAVASCRIPT, undefined, UndoModes.ENTIRE_SCRIPT, 'Rename Styles By Language');
/**
* Shows UI for Name Styles By Language
* @param {Object} settings - the settings to adjust via UI.
* @returns {1|2} - result code
*/
function ui(settings) {
// load last-used languages from document
settings.toLanguage = settings.doc.extractLabel('renameFromLanguage') || settings.toLanguage;
settings.fromLanguage = settings.doc.extractLabel('renameToLanguage') || settings.fromLanguage;
var w = new Window("dialog", 'Rename Styles By Language', undefined),
fromMenuGroup = w.add('group {orientation:"row", alignment:["left","top"], alignChildren: ["left","top"], margins:[10,10,10,20], preferredSize: [120,-1] }'),
fromlanguageMenu = fromMenuGroup.add('dropDownList { title: "From", preferredSize:[150,-1] }'),
spacer = fromMenuGroup.add('group {orientation:"column", preferredSize: [20,-1] }'),
tolanguageMenu = fromMenuGroup.add('dropDownList { title: "To", preferredSize:[150,-1] }'),
buttons = w.add("Group { orientation: 'row', alignment: ['right','bottom'], margins:[0,0,0,6] }"),
cancelButton = buttons.add("Button { text:'Cancel', properties:{name:'cancel'} }"),
renameButton = buttons.add("Button { text:'Rename Styles', enabled:false, enabled: true, name: 'ok' }");
// populate the language menus
var fromSelected = 0,
toSelected = 1,
index = 0;
for (var langName in settings.languages) {
if (settings.languages.hasOwnProperty(langName)) {
fromlanguageMenu.add('item', langName);
tolanguageMenu.add('item', langName);
if (settings.fromLanguage === langName)
fromSelected = index;
if (settings.toLanguage === langName)
toSelected = index;
}
index++;
}
fromlanguageMenu.selection = fromSelected;
tolanguageMenu.selection = toSelected;
renameButton.onClick = function () {
// update settings
settings.fromLanguage = fromlanguageMenu.selection.text;
settings.toLanguage = tolanguageMenu.selection.text;
// store last-used languages in document
settings.doc.insertLabel('renameToLanguage', settings.toLanguage);
settings.doc.insertLabel('renameFromLanguage', settings.fromLanguage);
// close window with success code
w.close(1);
};
w.center();
return w.show();
};
/**
* Returns a thing with matching property.
* If `key` is undefined, evaluate the object itself.
* @author m1b
* @version 2024-04-21
* @param {Array|Collection} things - the things to look through.
* @param {String} [key] - the property name (default: undefined).
* @param {*} value - the value to match.
* @returns {*?} - the thing, if found.
*/
function getThing(things, key, value) {
for (var i = 0, obj; i < things.length; i++)
if ((undefined == key ? things[i] : things[i][key]) == value)
return things[i];
};
Copy link to clipboard
Copied
Wow! That looks like a ton of work—thanks so much! Honestly, I'm quite tired right now, and it may be tomorrow before I gather the energy to try it out. (I'm in Australia, by the way.) But I will do so, and let you know.
Once I try it out, I will give you some feedback and that may clarify my workflow for you. But in a nutshell: I maintain all the stylesheets in their own InDesign document, which I'll call 'Style Guide'. I use this document to keep the stylesheets in sync across all the working documents: every time I work on a document, I resync from Style Guide using 'Load all text styles'. This ensures every document is constantly updated with the latest set of stylesheets.
Some stylesheets have numbering styles that use prefixes: for example, images are auto-numbered Figure 1, Figure 2, Figure n by a stylesheet ('Caption') that contains the number code:
Figure ^#:^>
When the document is translated (say, to Italian), that comes back to me as:
Figura ^#:^>
Sometime later, I make a change to 'Style Guide'. Perhaps the Table Label style gets modified. Or a different style. Or maybe I'm making another new document type which requires a whole new stylesheet.
Now I'm asked to replace a screenshot of our software which appears in our Italian document. This doesn't require translation: it's a straight replacement. Even the caption (Figura 2) won't change. However, when I open the Italian document, my process requires me to reimport all the stylesheets. At which point, the Caption stylesheet reverts from Figura to Figure. Meaning, I then have to then go and change it back manually.
Of course, one might ask: if none of the stylesheets in my Italian document are affected by the change to Style Guide, why reimport them? Because it becomes virtually impossible to track which stylesheets are used in which documents and when they were last updated. I would need to keep a log and analyze it every time I open a document: "The styles in this Italian document were last updated on mm/dd/yyyy. Since then, the following changes have been to Style Guide. Do I need to reupdate the stylesheets in this Italian document now, or not?"
But I avoid all that through discipline: every document always has the same set of stylesheets, and I know this, because every time I open a document I reload the styles regardless of whether I need to or not. I don't even need to think about, which in fact is sort of the point. But it does mean a lot of manual work re-updating styles which are localized.
I'll apologize if none of that made sense, but as mentioned, very tired. I'll try the script and let you know. Cheers!
Copy link to clipboard
Copied
[...] However, when I open the Italian document, my process requires me to reimport all the stylesheets. At which point, the Caption stylesheet reverts from Figura to Figure. Meaning, I then have to then go and change it back manually.[...]
By Alistair36395154jraa
Unless I'm missing something - you could have different stylesheets - for each language - and use them before and after the translation?
Copy link to clipboard
Copied
[...] Now I'm asked to replace a screenshot of our software [...]
By Alistair36395154jraa
This just caught my eye...
Does it means that you're translating ONLY files that belongs to your company - and not from outside?
Because that changes EVERYTHING...
You could have separate "templates" for specific languages and use Book feature more often.
Copy link to clipboard
Copied
Hi Robert,
Thanks for taking an interest in this. Sorry I've been slow responding but I've had some issues accessing this site.
I did look at ID-Tasker and it certainly has a lot of powerful features. Sadly, however, the business I work for is still in the start-up phase. It has no revenue and depends entirely on private investors. Even though the cost of ID-Tasker seems reasonable to me, they won't approve it. It took months just to get approval to subscribe to InDesign, and other low-cost apps or plug-ins have been rejected. Out of my hands, sorry.
Re the idea of Books: I don't know much about this feature, but the translation service requires us to treat each translated version of a document as an independent file. According to my limited understanding, I could bring all the translated versions of a document together in a single Book and that would sync the stylesheets. But let's imagine a stylesheet called 'Caption', which has a Number style which contains text so that each illustration can be autonumbered Figure 1, Figure 2 etc. That stylesheet exists in every document, except that the text strng is different in each case: one says 'Figure', another says 'Figura', etc. I don't see how the Books feature will help with that.
Cheers,
—Alistair
Copy link to clipboard
Copied
Was affraid that you're ignoring me 😉
I can always let you test full version for free - even for more than a few days 😉 but IDT will pay for itself in one day anyway 😉
In terms of the Book - book is just a "logical" binder for INDD files. They can still be treated = worked on - as a separate / independent files.
My "Book" idea is to use it just for synchronisation purposes - AND with different set of "source" files for each language.
If you start working on a new set of documents - you can create a new Book - one of those would be your "styles source" - then either work with this book - or on each file separately - then when you get your files back - open the Book and synchronise again.
Copy link to clipboard
Copied
Hi Mark, This morning I was writing a detailed and very appreciative response to your initial script when suddenly, for reasons totally beyond my comprehension, I found myself banned from the entire Community site. I've now gained access using a different email address but TBH, I am so completely disheartened that I've just given up. I wanted to let you know how much I appreciate the work you did. It wasn't quite what I wanted, which is my fault for not explaining properly in the first place.
What I wanted was to select a target language and have the Number code within certain paragraph styles (and the Title code within some TOVC styles) changed from the English to the selected language. When the translation service translates a document to, say, Italian, they modify the relevant stylesheets so that, for example, the numbering code "Figure ^#:^>" says "Figura ^#:^>" instead. But later, if I need to reimport the stylesheets so they have the latest font tweaks etc, they all get reset to English. Currently, I then have to manually edit them back to Italian etc. I was seeking to automate that. I won't need to I wrote a more detailed explanation this morning, including screenshots of the stylesheets dialogs, but then lost it all when I was banned. Anyway, thanks again. Cheers!
Copy link to clipboard
Copied
I won't need to I wrote a more detailed explanation this morning, including screenshots of the stylesheets dialogs, but then lost it all when I was banned."
By alistairl91300413
Ignore "I won't need to". Poorly edited!
Copy link to clipboard
Copied
Hi @Alistair36395154jraa ( @alistairl91300413 ) very sorry to hear about your difficulty. I asked a moderator to look at your original account and they don't think you seem to be banned. Everything seems normal. Did you receive any documentation about the ban? It's very strange.
As for the task at hand, I think you need the script to also perform the same translations through the Numbering Lists. I can modifiy it to do that, but give me a day or so; I'm a bit busy today.
- Mark
Copy link to clipboard
Copied
Hi Mark,
Re my access: thanks for checking with a moderator. I don't know how to contact them. When I attempt to access this site using my other account, which is through my company's account, I get an error page which says "You are not allowed to access this site." (I have a screenshot.) That is quickly replaced by another page which says "An unexpected error has occurred." I have no idea what's up with that but I'm not going to worry about it too much, as I can use this account anyway.
I totally understand you're busy. No hurry! For me, any help I get is a pure (and very welcome!) bonus.
Yes, the translations need to be applied to the Numbering lists. Also, the Table of Contents styles. The actual stylesheet names don't need to change: they can stay in English. The reason is that these changes are always the very last thing that happens to a translated document, before it is exported as a PDF and published to our customers.
The usual workflow is: we send the English document to the translators > they translate the document (including the text in those stylesheets) and return it > we make a PDF and publish. So far, all well and good.
The issue occurs when, independently of all that, I need to add, remove or tweak a stylesheet, usually for cosmetic reasons. Eventually, I would hope these are rare events, but right now we are a young business and still sorting all these things out. So for the foreseeable future, the tweaking will continue. Simply tweaking a stylesheet doesn't require the help of the translators. To make the change, and keep all the stylesheets synced up over all the documents, I first modify the English stylesheet, then reimport that entire set into the other language editions. As far as I know, that's the only way to make sure all the stylesheets remain consistent across all the documents.
But of course, when I reimport the English stylesheets, all those styles which contain text that was translated are now reset to English. When I provide the English document to the translators, the style 'Caption' contained a Number string with the text 'Figure'. When they send the document back, 'Figure' has been modified to read 'Εικόνα'. But if I subsequently reimport the English stylesheets to keep them in sync, 'Εικόνα' will be changed back to 'Figure'. Currently, I have to go through and reinstate the translated text, but it's laborious. That's why I'm looking for the script.
I hope this helps!
Cheers!
—Alistair
Copy link to clipboard
Copied
Copy link to clipboard
Copied
Hi Mark,
I've been away for several weeks, which has delayed my ability to respond further. Of course, if you have moved on to something more interesting, I understand. But I have tried to adapt your script and it is beyond my humble abilities. So I will have one more shot at explaining my workflow and what the script needs to do. (To be clear: I take full responsibility for not having explained this clearly the first time, and am sorry to have wasted your time.)
Putting translations aside for a minute, the underlying issue is how to manage and synchronise stylesheets (paragraph, and Table of Contents) across dozens, and eventually hundreds, of different documents. My client makes medical devices which require a lot of documents, most of them mandated by various authorities. Currently, in English, we have 63 different types of document (user guides, safety data sheets etc) across our product range, and that number is growing. Of course, the company wants those documents to have consistent typography. As a result, due to the sheer variety of documents in question, we currently have 78 unique paragraph styles.
While I would like to say those styles are written in stone and never change, the reality is that they are constantly being tweaked. This raises the question of how to manage them and keep them consistent over such a large range of documents? This is not a new problem: the forums are littered with designers asking the same question. The two most common answers, proposed by most experts, are:
- Maintain your styles in a single 'source' document. Then whenever you edit a document that uses those styles, use 'Load All Text Styles' from the source document, overriding those in the 'child' document. This is the method I use.
- Use the Books feature. I am not using this (I do have reasons, but am not elucidating them here only to save space).
This works fine—and if all our documents were in English, I would not need any help.
But each of those 60+ documents also needs to be available in multiple languages (currently 4, with 3 others on the 'to do' list and eventually many more). For me, the workflow is straightforward: once all the stakeholders have signed off on the English version of a document, I package it up and send to our external translation service. During the translation process, some of the styles are modified to accommodate the foreign language. (One of the other posters, Joel, has written extensively about how the translators do this, but from my perspective, all I know is that when the document comes back to me, certain styles have been modified to accommodate foreign text, and this makes sense.) Here is an example:
The style for our captions follows the form, Figure #: yadda-yadda-yadda. In order to take advantage of automated caption numbering, I use ID's Bullets and Numering feature. Specifically, I have a style called 'Figure', which contains the following entry in the Number field under Bullets and Numbering:
Figure ^#:^>
Likewise, I have a similar approach for auto-numbering tables, chapters, appendices, revision notes, table of contents, table of tables and table of figures.
When the translated document comes back to me, these styles have been modified. So in an Italian document, the style 'Figure' (noted above) would be modified so that the Number field contains:
Figura ^#:^>
And that would be just fine, so long as I don't subsequently need to update the stylesheets from my 'source' document. Because as soon as I do that, the Italian 'Figura' gets changed back to the English 'Figure'.
Just yesterday, for example, we discovered that our basic text font does not include the glyphs ≥ and ≤, which causes an 'unknown glyph' error. To fix that, I have modified the Basic paragraph stylesheet (in our 'source' document) to include a GREP style which applies a different font to those characters. And in doing so, I discovered that some paragraph styles, which should be based on Basic, were erroneously based on 'No Paragraph Style'. So those also had to be edited to use the Basic style as their base.
So now I need to update the styles in every single document based on the source, including dozens of translated documents. And when I do that, all the translations of 'Figure', 'Table', 'Revision', 'Chapter', 'Appendix' etc will revert back to English. I then have to manually restore the foreign terms into the relevant stylesheets. I keep a list of the specific stylesheets and the foreign language terms I need for each language. For example, the stylesheet for numbering tables:
Paragraph style = 'Table Number'
Attribute = 'Bullets and Numbering | Number field'
- English = Table ^#:^>
- Greek = Πίνακα ^#:^>
- Italian = Tabella ^#:^>
- Spanish = Tabla ^#:^>
- Portuguese = Tabela ^#:^>
But to modify these styles, for a dozen or so stylesheets, for a growing range of languages, across dozens (and growing) of documents, is a monumental task. It is also exceedingly boring 🙂
So what I am looking for is a script that will do that for me. For example:
- I send an English for translation into Greek. The document has a paragraph stylesheet called 'Table Number', where the attribute Bullets and Numbering | Number is set to Table ^#:^>
- The translators send the document back in Greek. The Number field of 'Table Number' now says Πίνακα ^#:^> instead of Table ^#:^>
- Sometime later, my source stylesheets are modified, so I now need to update all of our documents. I open each document and invoke 'Load All Text Styles' from my source document. But when I do this on my Greek document, all the styles with Greek text revert back to English (Πίνακα ^#:^> changes to Table ^#:^>)
- I run the script. A dialog pops up, asking which language I need to use. I select Greek.
- The script modifies the specified styles (for example, it changes the Number field in the stylesheet 'Table Number' from Table ^#:^> back to the Greek Πίνακα ^#:^>)
The script would need to deal with TOC styles as well as paragraph styles. Of course, over time, I will need to add more languages (but based on your earlier script, I am confident I could do that!), and possibly more stylesheets.
I apologise for the length and detail of that description. Please let me know if it now makes sense and if you are willing to help!
Cheers,
--Alistair
Copy link to clipboard
Copied
Pretty much everything on your list can be done by loading styles from a template for a specific language.
Copy link to clipboard
Copied
Yes, that would simply the problem a little. There are two variations that I can see:
- Maintain a different 'template' for each language. When I modify the English template, I will still to update the foreign versions. I can do this by manually replicatng the change in each template. Or I could upload the English styles into each temp;late, but then I am back to square one: I have lost my translations. (Admittedly, though, I would only need to fix these styles in the foreign templates, rather than every foreign document.)
- Use a single template, but include different variants of each stylesheet, one for each language. I actually did this initially, before realising it would result in literally hundreds of stylesheets.
If Mark isn't able to help me out with a script, I am most likely to go with option #1. Option #2 would be smoother (I could base each foreign stylesheet on its English equivalent) but I am concerned about the number of styles that would require.
Cheers!
--Alistair
Copy link to clipboard
Copied
I don't think that script that just changes a few words is a solution for you...
You rather need something that will allow you to keep all the templates separated - but also synchronised.
Or - but it would probably need further testing - you could have a Book with templates - use it to synchronise those templates with a master English template - and another set of Books - for each language - that will use language specific file / template from the 1st Book.
INDD file can belong to many different Books - and have different roles in each - but when open on its own - it has no idea that it belongs to any Book.
Please check your private messages - top right corner of this website.
Copy link to clipboard
Copied
Hi @Alistair36395154jraa I've written a script that converts all paragraph styles the way you describe I think. Give it a try and let me know what you think. Try using my attached demo.indd first to make sure the script is working on that.
- Mark
Example: notice that the hyphenation changes when the language changes.
/**
* @file Convert Styles To Language.js
*
* Processes the active document's paragraph styles, to:
* - convert words used in numbering expressions
* - set the applied language.
*
* Edit the `settings` object below as needed.
*
* @author m1b
* @version 2025-04-27
* @discussion https://community.adobe.com/t5/indesign-discussions/script-to-modify-paragraph-styles-based-on-user-selected-input-value/m-p/15226562
*/
function main() {
var settings = {
/** the translation languages; add more as you need. CHECK THESE PROPERLY, THEY ARE JUST PLACEHOLDERS FOR NOW */
languages: {
'English': { words: ['Appendix', 'Chapter', 'Figure', 'Table'], appliedLanguage: 'English: USA' },
'German': { words: ['Anhang', 'Kapitel', 'Abbildung', 'Tabelle'], appliedLanguage: 'German: 2006 Reform' },
'Greek': { words: ['Παράρτημα', 'Κεφάλαιο', 'Εικόνα', 'Πίνακα'], appliedLanguage: 'Greek' },
'Spanish': { words: ['Apéndice', 'Capítulo', 'Figura', 'Tabla'], appliedLanguage: 'Spanish' },
},
/** the language to translate from */
fromLanguage: 'English',
/** the language to translate to */
toLanguage: 'Spanish',
/** whether to show UI */
showUI: true,
/** whether to show user how many translations were made */
showResults: false,
};
if (0 === app.documents.length)
return alert('Please open a document and try again.');
var doc = settings.doc = app.activeDocument;
if (
settings.showUI
&& 2 === ui(settings)
)
// user cancelled UI
return;
try {
// make a converter for the purposes of this script
var convertLanguage = makeConverter(settings.languages[settings.fromLanguage], settings.languages[settings.toLanguage]);
}
catch (error) {
return alert(error);
}
/* ------------------------ *
* 1. PARAGRAPH STYLES *
* ------------------------ */
// collect all the styles to rename
var styles = doc.allParagraphStyles;
for (var i = styles.length - 1; i >= 0; i--) {
convertLanguage(styles[i]);
}
if (settings.showResults)
alert('Translation Complete.');
};
app.doScript(main, ScriptLanguage.JAVASCRIPT, undefined, UndoModes.ENTIRE_SCRIPT, 'Convert Styles Language');
/**
* Shows UI for Name Styles By Language
* @param {Object} settings - the settings to adjust via UI.
* @returns {1|2} - result code
*/
function ui(settings) {
// load last-used languages from document
settings.toLanguage = settings.doc.extractLabel('convertToLanguage') || settings.toLanguage;
settings.fromLanguage = settings.doc.extractLabel('convertFromLanguage') || settings.fromLanguage;
var w = new Window("dialog", 'Convert Styles Language', undefined),
fromMenuGroup = w.add('group {orientation:"row", alignment:["left","top"], alignChildren: ["left","top"], margins:[10,10,10,20], preferredSize: [120,-1] }'),
fromLanguageMenu = fromMenuGroup.add('dropDownList { title: "From", preferredSize:[150,-1] }'),
spacer = fromMenuGroup.add('group {orientation:"column", preferredSize: [20,-1] }'),
toLanguageMenu = fromMenuGroup.add('dropDownList { title: "To", preferredSize:[150,-1] }'),
buttons = w.add("Group { orientation: 'row', alignment: ['right','bottom'], margins:[0,0,0,6] }"),
cancelButton = buttons.add("Button { text:'Cancel', properties:{name:'cancel'} }"),
convertButton = buttons.add("Button { text:'Convert', enabled:false, enabled: true, name: 'ok' }");
// populate the language menus
var fromSelected = 0,
toSelected = 1,
index = 0;
for (var langName in settings.languages) {
if (settings.languages.hasOwnProperty(langName)) {
fromLanguageMenu.add('item', langName);
toLanguageMenu.add('item', langName);
if (settings.fromLanguage === langName)
fromSelected = index;
if (settings.toLanguage === langName)
toSelected = index;
}
index++;
}
fromLanguageMenu.selection = fromSelected;
toLanguageMenu.selection = toSelected;
convertButton.onClick = function () {
// update settings
settings.fromLanguage = fromLanguageMenu.selection.text;
settings.toLanguage = toLanguageMenu.selection.text;
// store last-used languages in document
settings.doc.insertLabel('convertToLanguage', settings.toLanguage);
settings.doc.insertLabel('convertFromLanguage', settings.fromLanguage);
// close window with success code
w.close(1);
};
w.center();
return w.show();
};
/**
* Returns a thing with matching property.
* If `key` is undefined, evaluate the object itself.
* @author m1b
* @version 2024-04-21
* @param {Array|Collection} things - the things to look through.
* @param {String} [key] - the property name (default: undefined).
* @param {*} value - the value to match.
* @returns {*?} - the thing, if found.
*/
function getThing(things, key, value) {
for (var i = 0, obj; i < things.length; i++)
if ((undefined == key ? things[i] : things[i][key]) == value)
return things[i];
};
/**
* Returns `str` after replacing `fromWords` with `toWords`.
* @author m1b
* @version 2025-04-27
* @param {String} str - the string to convert.
* @param {Array<String>} fromWords - the words to replace.
* @param {Array<String>} toWords - the replacement words.
* @returns {String}
*/
function convertString(str, fromWords, toWords) {
for (var i = 0; i < fromWords.length; i++)
str = str.replace(fromWords[i], toWords[i]);
return str;
};
/**
* Returns a conversion function, configured
* to convert `from` to `to`.
*
* `from` and `to` have these properties:
* {
* words: {Array<String>} - the words to find/replace.
* appliedLanguage: {String} - the ID of an Indesign LanguageWithVendors.
* }
*
* @author m1b
* @version 2025-04-27
* @param {Object} from - object containing details of the language conversion.
* @param {Object} to - object containing details of the conversion.
* @returns {String}
*/
function makeConverter(from, to) {
var fromWords = from.words,
toWords = to.words,
appliedLanguage = getThing(app.languagesWithVendors, 'name', to.appliedLanguage);
if (!appliedLanguage)
throw new Error('makeConverter: language with vendors "' + to.appliedLanguage + '" not found. Please use the correct applied language string.');
return convert;
/**
* Performs a conversion on `thing`.
* @param {ParagraphStyle|String} thing - the thing to convert.
* @returns {String?} - returns converted String if `thing` is String.
*/
function convert(thing) {
if ('String' === thing.constructor.name)
return convertString(thing, fromWords, toWords);
else if ('ParagraphStyle' === thing.constructor.name) {
if (thing.name[0] === '[')
// don't process style that starts with a square bracket, eg. '[None]'
return;
// thing.appliedLanguage = to.appliedLanguage;
thing.numberingExpression = convert(thing.numberingExpression);
}
};
};
Copy link to clipboard
Copied
Hi Mark,
Thanks for revisiting this for me. Based on your animated screenshot, the new script appears to do what I need. As suggested, I downloaded your sample file when I run the script I get an error:
In regards to hyphenation: yes, I would expect it to change in response to the language setting. Curiously, the translators left the language setting at English. However, since I have turned hyphenation off in these documents, it is a moot point.
Cheers!
--Alistair
Copy link to clipboard
Copied
Hi @Alistair36395154jraa that error is a bit mysterious. I've updated the script above, can you copy it again and try once more. I've also commented out line 226 which is where it sets the `appliedLanguage`.
- Mark
Copy link to clipboard
Copied
Hi Mark,
Yes! That works! Thank you so much! I was also able to modify the language sets and add some new ones. It doesn't matter that your script no longer sets the language attribute, since I don't need that anyway. (For whatever reason, the translators left the language setting as "English (UK)", and if it didn't worry them, it certainly doesn't worry me!)
My only comment (not super important) is that the script does a little bit more than I absolutely need. That's because, in our workflow, we always start with English, so I never need to select a different 'from' language. But it doesn't hurt to leave it in: it's not causing any bother.
Once again: thanks very much, and sincerely appreciated!
Cheers,
--Alistair
Copy link to clipboard
Copied
Hi Alistair, good to hear it is useful. I decided to leave in the "from" language, hoping that it wouldn't get in the way, but if you want to turn it off, just change these 4 lines (lines 92-95 in my unmodified script):
fromMenuGroup = w.add('group {orientation:"row", alignment:["left","top"], alignChildren: ["left","top"], margins:[10,10,10,20], preferredSize: [120,-1] }'),
fromLanguageMenu = fromMenuGroup.add('dropDownList { title: "From", preferredSize:[150,-1] }'),
spacer = fromMenuGroup.add('group {orientation:"column", preferredSize: [20,-1] }'),
toLanguageMenu = fromMenuGroup.add('dropDownList { title: "To", preferredSize:[150,-1] }'),
to these 3 lines
fromMenuGroup = w.add('group {orientation:"row", alignment:["left","top"], alignChildren: ["left","top"], margins:[10,10,10,0], preferredSize: [120,-1] }'),
fromLanguageMenu = w.add('dropDownList { title: "From", preferredSize:[150,-1], visible: false }'),
toLanguageMenu = fromMenuGroup.add('dropDownList { title: "To", preferredSize:[150,-1] }'),
which just makes the "from" menu invisible.
- Mark

