关于 javascript:使用 Photoshop 脚本更改选定的文本图层语言

Changing selected text layers language with photoshop script

虽然我设法将一个功能性脚本一起更改所选图层的字典语言,但这还不是我所需要的。

我目前正在检索我选择的图层的索引,使用它们来获取图层名称——这是有问题的部分——然后根据我显示的自定义对话框中选择的选项使用魔法来更改它们的语言。

图层名称的使用是一个非常不成熟的解决方案,我需要精确,我需要能够根据图层 ID 或索引更改语言。不仅我的脚本容易出现名称冲突,而且我不知道这些选定的图层将在哪里,如果在文档的根目录上或在 5 个组堆栈内。

这是我当前的代码:

主函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function main() {
    // Create window with language selection and retrieve selected value
    var lang = createWindow();

   // Retrieve selected layers
   var selectedLayers = getSelectedLayersIdx();

   // Look at each entry and change language when possible
   for(var a in selectedLayers){
        try {
           setLangByIndex(Number( selectedLayers[a]), lang );
        } catch(err) {   }
   }
}

(createWindow 返回一个 lang 值,跳过它)

迈克得到身份证

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
function  getSelectedLayersIdx(){
    var selectedLayers = new Array;
    var ref = new ActionReference();
    ref.putEnumerated( charIDToTypeID('Dcmn'), charIDToTypeID('Ordn'), charIDToTypeID('Trgt') );
    var desc = executeActionGet(ref);
    if( desc.hasKey( stringIDToTypeID( 'targetLayers' ) ) ) {
        desc = desc.getList( stringIDToTypeID( 'targetLayers' ));
        var c = desc.count
        var selectedLayers = new Array();
        for(var i=0;i<c;i++) {
            try{
                activeDocument.backgroundLayer;
                selectedLayers.push(  desc.getReference( i ).getIndex() );
            } catch(e) {
                selectedLayers.push(  desc.getReference( i ).getIndex()+1 );
            }
        }
    } else {
        var ref = new ActionReference();
        ref.putProperty( charIDToTypeID('Prpr') , charIDToTypeID( 'ItmI' ));
        ref.putEnumerated( charIDToTypeID('Lyr '), charIDToTypeID('Ordn'), charIDToTypeID('Trgt') );
        try {
            activeDocument.backgroundLayer;
            selectedLayers.push( executeActionGet(ref).getInteger(charIDToTypeID( 'ItmI' ))-1);
        } catch(e) {
            selectedLayers.push( executeActionGet(ref).getInteger(charIDToTypeID( 'ItmI' )));
        }
    }
    return selectedLayers;
}

设置语言的函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function setLangByIndex(idx, lang){
    ref = new ActionReference();
    ref.putProperty( charIDToTypeID("Prpr") , charIDToTypeID("Nm " ));
    ref.putIndex( charIDToTypeID("Lyr" ), idx );
    var name = executeActionGet(ref).getString(charIDToTypeID("Nm " ));

    var el = activeDocument.layers.getByName( name );
    // Temp quick block; MUST UPDATE IN CASE OF NEW LANGUAGES
     if (lang == 'pt_br' )
        el.textItem.language = Language.BRAZILLIANPORTUGUESE;
    else if (lang == 'en_us' )
        el.textItem.language = Language.ENGLISHUSA;
    else
        el.textItem.language = Language.ENGLISHUK;
}

我尝试低效的解决方法:

  • 使用 Adob??e 的脚本侦听器通过 executeAction 更改语言,
    但无法使其工作。语言部分在?4堆叠内
    描述符(和一个列表!)。我迷路了,不断收到错误 8800。
  • 弄清楚如何使用 idx 获取对象 ref。失败的
    悲惨地。


在我注意到与段落样式相关的一些烦人的故障(您可以将其定义为 PS 上文本的默认设置,而不是 JS 对象)之后,我放弃了固执并停止避免通过索引数组执行新循环完成后重新选择图层。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
/*
   *  Based in Mike Hale's"getSelectedLayersIdx" script and Adobe's Scripting Listener dump.
      Based the panel on Davide Barranca's code: http://www.davidebarranca.com/2012/10/scriptui-window-in-photoshop-palette-vs-dialog/

      Useful Resources:
      Photoshop char list: http://www.pcpix.com/Photoshop/char.htm
      ActionDescriptor methods: http://jongware.mit.edu/pscs5js_html/psjscs5/pc_ActionDescriptor.html
      TextItem methods: http://jongware.mit.edu/pscs5js_html/psjscs5/pc_TextItem.html
      You can fish for language codes here: http://wingp.googlecode.com/svn/photogp/photoshopapi/photoshop/PIStringTerminology.h
*/


/* ______________________________ SCRIPT ______________________________ */
var scriptAlert ="Language Change says";

// MUST UPDATE IF YOU WANT TO CHANGE THE AVAILABLE LANGUAGES
// The available languages, as { text displayed on dialog window : codename }. See notes above for more language codes
var langs = {};
langs['Português (Brasil)'] = 'brazilianPortugueseLanguage';
langs['English (UK)'] = 'ukenglishLanguage';
langs['English (USA)'] = 'englishLanguage';

if(app.documents.length>0){ // the script will be executed  only if an active document exists.

    var imgName = activeDocument.name;
    var extreme= imgName.substr(imgName.length - 5, 5);
    var dot = extreme.lastIndexOf(".");

    if(dot == -1) { // Checks if the active document  was saved or not.
        alert("Please, save your document!", scriptAlert, false);
    } else {
        main(); // if the active document was saved, go ahead!
    }
}


function createWindow() { // Creates a panel asking for input
        var isDone, win, windowResource, radio_group, cancel, rb, i;

        //sentinel variable
        isDone = false;
        cancel = false;

        // Build dialog radio buttons
        i = 0;
        for( var k in langs ) {
            if( i==0 )
                rb ="rb"+i+": RadioButton { text:  '"+k+"', value: 1 }, ";
            else
                rb +="rb"+i+": RadioButton { text:  '"+k+"' }, ";
            i++;
        }

        windowResource ="palette {  \\
            orientation: 'column', \\
            alignChildren: ['fill', 'top'],  \\
            preferredSize:[300, 130], \\
            text: 'Change Spell Check Language',  \\
            margins:15, \\
            \\
            optPanel: Panel { \\
                orientation: 'row', \\
                alignChildren: 'left', \\
                margins:15, \\
                text: ' Select the desired dictionary language for the select text ', "
+  rb +" \\
                } \\
            \\
            bottomGroup: Group{ \\
                cancelButton: Button { text: 'Cancel', properties:{name:'cancel'}, size: [120,24], alignment:['right', 'center'] }, \\
                applyButton: Button { text: 'Ok', properties:{name:'ok'}, size: [120,24], alignment:['right', 'center'], active: true }, \\
            }\\
        }"
;
        win = new Window(windowResource);

        radio_group = win.optPanel; // set group

        // Match options with language
        function selected_rbutton (rbuttons)
        {
             for (var i = 0; i < rbuttons.children.length; i++)
                 if (rbuttons.children[i].value == true)
                    return langs[rbuttons.children[i].text];
         }

        win.bottomGroup.cancelButton.onClick = function() {
            win.close();
            return cancel = true;
        };      
        // Button listeners
        win.bottomGroup.applyButton.onClick = function() {
          return isDone = true;
        };            
        // don't forget this one!
        win.onClose = function() {
            return cancel = true;
        };

        win.addEventListener("keydown", function (k)
         {
             if (k.keyName == 'Enter')
                return isDone = true;
         });

        win.show();

        while (isDone === false) {
            try {
                app.refresh();
            } catch(err) { // Esc cancels without errors
                return false;
            }
        }

       return cancel ?  false : selected_rbutton (radio_group); // return value, or false if cancelled
}


function  getSelectedLayersIdx(){ // Gets array of indexes of selected layers
    var selectedLayers = new Array;
    var ref = new ActionReference();
    ref.putEnumerated( charIDToTypeID('Dcmn'), charIDToTypeID('Ordn'), charIDToTypeID('Trgt') );
    var desc = executeActionGet(ref);
    if( desc.hasKey( stringIDToTypeID( 'targetLayers' ) ) ) {
        desc = desc.getList( stringIDToTypeID( 'targetLayers' ));
        var c = desc.count
        var selectedLayers = new Array();
        for(var i=0;i<c;i++) {
            try{
                activeDocument.backgroundLayer;
                selectedLayers.push(  desc.getReference( i ).getIndex() );
            } catch(e) {
                selectedLayers.push(  desc.getReference( i ).getIndex()+1 );
            }
        }
    } else {
        var ref = new ActionReference();
        ref.putProperty( charIDToTypeID('Prpr') , charIDToTypeID( 'ItmI' ));
        ref.putEnumerated( charIDToTypeID('Lyr '), charIDToTypeID('Ordn'), charIDToTypeID('Trgt') );
        try {
            activeDocument.backgroundLayer;
            selectedLayers.push( executeActionGet(ref).getInteger(charIDToTypeID( 'ItmI' ))-1);
        } catch(e) {
            selectedLayers.push( executeActionGet(ref).getInteger(charIDToTypeID( 'ItmI' )));
        }
    }
    return selectedLayers;
}


function selectLayerByIndex( selectedLayers, add ){ // Selects layers by index. If fed an array + true add, selects them, otherwise provide a single value so it selects a single layer
    if (typeof(add)==='undefined') add = false;

    if ( add ) // If Add it's an array
        for(var a in selectedLayers){
            var desc = new ActionDescriptor();
                var ref = new ActionReference();
                ref.putIndex( charIDToTypeID("Lyr" ), Number(selectedLayers[a]) );
            desc.putReference( charIDToTypeID("null" ), ref );
            desc.putEnumerated( stringIDToTypeID("selectionModifier" ), stringIDToTypeID("selectionModifierType" ), stringIDToTypeID("addToSelection" ) );
            var idMkVs = charIDToTypeID("MkVs" );
            desc.putBoolean( charIDToTypeID("MkVs" ), false );

            executeAction( charIDToTypeID("slct" ), desc, DialogModes.NO );
        }
    else // Else I just need to make this layer active, it's a number
    {
            var desc = new ActionDescriptor();
                var ref = new ActionReference();
                var idLyr = charIDToTypeID("Lyr" );
                ref.putIndex( charIDToTypeID("Lyr" ), selectedLayers );
            desc.putReference( charIDToTypeID("null" ), ref );
            desc.putBoolean( charIDToTypeID("MkVs" ), false );
        executeAction( charIDToTypeID("slct" ), desc, DialogModes.NO );
    }
}


function setLangByIndex( idx, lang ){ // Sets the dictionary language for a text layer based on its index
// Make layer active
    selectLayerByIndex( idx );

// And do tiny override
    var textObj = new ActionDescriptor();
        var target = new ActionReference();
        target.putProperty( charIDToTypeID("Prpr" ), charIDToTypeID("TxtS" ) ); // desired property: text style
        target.putEnumerated( charIDToTypeID("TxLr" ), charIDToTypeID("Ordn" ), charIDToTypeID("Trgt" ) ); // the active layer
    textObj.putReference( charIDToTypeID("null" ), target );
        var textStyle = new ActionDescriptor();
        textStyle.putInteger( stringIDToTypeID("textOverrideFeatureName" ), 808466225 );
        textStyle.putInteger( stringIDToTypeID("typeStyleOperationType" ), 3 );
        textStyle.putEnumerated( stringIDToTypeID("textLanguage" ), stringIDToTypeID("textLanguage" ), stringIDToTypeID( lang ) );

    textObj.putObject( charIDToTypeID("T  " ), charIDToTypeID("TxtS" ), textStyle ); // to (end); text style, desc.
executeAction( charIDToTypeID("setd" ), textObj, DialogModes.NO ); // execute
}


////////////////////////////////////
// Main function
function main() {
    // Create window with language selection and retrieve selected value
    var lang = createWindow();

    if ( !lang ) // If cancelled please stop
        return;

     // Retrieve selected layers
     var selectedLayers = getSelectedLayersIdx();

    // Look at each entry and change language when possible; otherwise skip to next item
    for(var k in selectedLayers){
       try {
            setLangByIndex(Number(selectedLayers[k]), lang);
        } catch(err) {
            continue;
        }
    }
    selectLayerByIndex( selectedLayers, true );
}