Assegna la lingua predefinita della tastiera per applicazione


11

È possibile assegnare la lingua predefinita della tastiera per applicazioni specifiche? So che esiste un'opzione per avviare sempre un'applicazione con una lingua predefinita della tastiera, ma questo non è quello che voglio.

Sto cercando qualcosa di simile alle "aree di lavoro fisse" che puoi impostare usando CompizConfig (hai impostato Chrome per aprire sempre su X1Y1, terminale su X2Y1 ecc.). Qualcosa in cui impostarei Chrome: ceco, terminale: inglese, Spotify: inglese, ...


In "Inserimento testo" è presente l'opzione "Consenti origini diverse per ogni finestra". Forse un passo nella giusta direzione per te.
Gunnar Hjalmarsson,

Sì, grazie, lo so. Questo è il passo necessario che direi, ma sfortunatamente non è quello che voglio ottenere. Grazie comunque.
Grongor

C'è un modo di scrivere. Hai solo bisogno di quelle 3 app o ce ne sono altre? A seconda di quanto flessibile desideri che la sceneggiatura sia, potrebbe volerci più o meno tempo per scriverla
Sergiy Kolodyazhnyy,

@JacobVlijm Sembra un altro buon lavoro per Python;)
Sergiy Kolodyazhnyy il

Ha inviato una risposta. Fammi sapere cosa ne pensi
Sergiy Kolodyazhnyy il

Risposte:


6

introduzione

Il seguente script imposta la lingua per ciascun programma definito dall'utente, in base alla posizione di quella lingua nel menu della lingua. Ad esempio, se il mio ordine è: inglese (1), cinese (2) e russo (3), posso impostare Firefox per avere la lingua 2, terminale per avere la lingua 1 e LibreOffice per avere la lingua 3.

Lo script è diviso in due parti: la prima è lo script effettivo che fa il lavoro, il secondo script funge da elemento di controllo. L'idea è di eseguire lo script di impostazione della lingua come applicazione di avvio e ogni volta che è necessario cambiare manualmente la lingua: fare doppio clic sul collegamento allo script del controller.

Pre-requisiti

  1. Installa il wmctrlprogramma con sudo apt-get install wmctrl.

copione

#!/bin/sh
# Author: Serg Kolo
# Date: August 4, 2015
# Description: This script forces assigned input languages
#              for specific windows
# Version:2

# Use this part to set programs and their respective languages
# PROG_CLASS or a running window can be found with the
# wmctrl -lx command
# If you want to add another program to the list, 
# follow the template PROG_CLASS_num=window.Class
# and bellow that $LANGnum=num


PROG_CLASS_1=gedit.Gedit
LANG1=2

PROG_CLASS_2=gnome-terminal-server.Gnome-terminal
LANG2=0

PROG_CLASS_3=Navigator.Firefox
LANG3=1


# While loop below gets the job done. 
# If you need to send languages for more programs -  copy  
# the first entry and replace  $PROG_CLASS_1 with $PROG_CLASS_num
# where num is respective number of a program
# Replace $LANGnum with the respective language number. After the "="
# post positional number of the language you want to use. 
# Remember the count starts from 0

while [ 1 ];do
  WM_CLASS=$(wmctrl -lx | awk -v search=$(printf %x $(xdotool getactivewindow)) '{ if($1~search) print $3 }' )
  CURRENT=$(gsettings get org.gnome.desktop.input-sources current| awk '{print $2}')
    case  $WM_CLASS in

      $PROG_CLASS_1)  
        if [ $CURRENT -ne  $LANG1 ];then
          gsettings set org.gnome.desktop.input-sources current $LANG1
        fi
      ;;

      $PROG_CLASS_2) 
        if [ $CURRENT -ne  $LANG2 ];then
          gsettings set org.gnome.desktop.input-sources current $LANG2
        fi  
      ;;

       $PROG_CLASS_3) 
         if [ $CURRENT -ne  $LANG3 ];then
           gsettings set org.gnome.desktop.input-sources current $LANG3
         fi  
        ;;
    esac

    sleep 0.250

done

Script del controller

#!/bin/sh
# set -x
# Author: Serg Kolo
# Date: August 8, 2015
# Description: Controller script for set-lang.sh script
# Allows pausing and resuming execution of set-lang.sh
STATUS=$(ps -o stat -p $(pgrep -o  set-lang.sh) | awk '{getline;print }')

case $STATUS in
    T) kill -CONT $(pgrep set-lang.sh) 
       notify-send 'RESUMED'
    ;;

    S) kill -STOP $(pgrep set-lang.sh)
       notify-send 'STOPED'
    ;;

    *) exit ;;
esac 

File di avvio (.desktop) per lo script set-lang.sh

[Desktop Entry]
Name=set-lang.sh
Comment=Script to set languages
Exec=/home/yourusername/bin/set-lang.sh
Type=Application
StartupNotify=true
Terminal=false

File di avvio (.desktop) per set-lang-controller.sh

[Desktop Entry]
Name=lang-control
Comment=Shortcut to controlling script
Exec=/home/yourusername/bin/set-lang-control.sh
Type=Application
StartupNotify=true
Terminal=false

Far funzionare la sceneggiatura

  1. Crea una cartella nella tua home directory chiamata bin. Puoi farlo nel file manager o usare il comando mkdir $HOME/binnel terminale
  2. Nella bincartella creare due file: set-lang.she set-lang-control.sh. Salva script in set-lang.she script controller in set-lang-control.sh. Rendi eseguibili entrambi gli script consudo chmod +x $HOME/bin/set-lang-control.sh $HOME/bin/set-lang.sh
  3. Crea due .desktopfile. Uno è set-lang.desktop. Deve essere inserito nella .config/autostartdirectory nascosta . Il secondo è set-lang-controller.desktop, può essere inserito nella tua bincartella. Quindi trascina e aggiungi al set-lang-controller.desktopfile di avvio il file. Questo diventerà il collegamento per interrompere temporaneamente e riprendere l'esecuzione dello script.

NOTA che la riga Exec=deve essere modificata per avere il tuo vero nome utente nel percorso dello script (perché questa è la tua home directory effettiva). Ad esempio, il mio sarebbeExec=/home/serg/bin/set-lang.sh

Spiegazione e personalizzazione:

Lo script stesso viene eseguito in un ciclo while infinito e controlla la finestra attiva corrente. Se la finestra attiva corrente corrisponde a una delle opzioni nella struttura del caso, passiamo alla lingua appropriata. Per evitare un'impostazione costante, ogni parte della struttura del caso ha un'istruzione if che verifica se la lingua è già stata impostata sul valore desiderato.

Il doppio clic sul pulsante di avvio per set-lang-controller.shcontrollerà lo stato dello set-lang.shscript; se lo script è in esecuzione, verrà messo in pausa e se lo script verrà messo in pausa verrà ripreso. Verrà mostrata una notifica con il messaggio appropriato.

Per personalizzare lo script, è possibile aprire le applicazioni desiderate, eseguire wmctrl -lxe prendere nota della terza colonna, la classe della finestra. Uscita campione:

$ wmctrl -lx | awk '$4="***" {print}'                                                                                                            
0x02c00007 0 gnome-terminal-server.Gnome-terminal *** Terminal
0x03a0000a 0 desktop_window.Nautilus *** Desktop
0x04a00002 0 N/A *** XdndCollectionWindowImp
0x04a00005 0 N/A *** unity-launcher
0x04a00008 0 N/A *** unity-panel
0x04a0000b 0 N/A *** unity-dash
0x04a0000c 0 N/A *** Hud
0x012000a6 0 Navigator.Firefox *** unity - Assign default keyboard language per-application - Ask Ubuntu - Mozilla Firefox

Selezionare le classi di finestre appropriate per ciascun programma. Successivamente, vai alla parte dello script che consente la personalizzazione e aggiungi due voci per PROG_CLASS e LANG. Quindi aggiungere la voce appropriata nella struttura del caso.

Ad esempio, se voglio aggiungere LibreOffice's Writer, apro la finestra di LibreOffice Writer, vado al terminale ed eseguo wmctrl -lx. Mi dirà che la finestra di Writer ha classe libreoffice.libreoffice-writer. Successivamente andrò allo script, aggiungerò PROG_CLASS_4=libreoffice.libreoffice-writere LANG4=3nell'area appropriata. Nota il numero corrispondente 4. Successivamente, vai alla struttura del caso e aggiungi la seguente voce tra last ;;e esac:

$PROG_CLASS_4) 
  if [ $CURRENT -ne  $LANG4 ];then
    gsettings set org.gnome.desktop.input-sources current $LANG4
  fi  
;;

Ancora una volta, nota il segno $ e il numero corrispondente 4.

Inoltre, se lo script viene eseguito come elemento di avvio automatico e si desidera arrestarlo temporaneamente per personalizzarlo, utilizzare pkill set-lang.she riprendere connohup set-lang.sh > /dev/null 2&>1 &

Piccola nota: un altro modo per scoprire la classe della finestra per un programma (quella roba che precede la singola parentesi tonda nella struttura del case) è usare questo xprope awkoneliner:xprop | awk '/WM_CLASS/ {gsub(/"/," "); print $3"."$5}


Grazie, è un buon inizio. L'unico (ma importante) problema è che non sarò in grado di cambiare la lingua in quelle applicazioni. Lo script sovrascriverà semplicemente le mie impostazioni in ogni momento. Vorrei poter cambiare la lingua anche in quelle finestre. Quindi forse aggiungi qualche controllo per il pid dell'applicazione e imponi il linguaggio solo la prima volta o qualcosa del genere?
grongor

Preferirei anche che questo script fosse guidato dagli eventi, non basato su loop. Non è un grosso problema, ma apprezzerei molto se tu potessi fornire un piccolo how-to per farlo funzionare con dbus o qualcosa del genere (se possibile).
grongor

@GRoNGoR, quindi ci ho pensato un po ', e finora non vedo un modo per mettere in pausa lo script tranne kill -STOP $(pgrep set-lang.sh)che per riprenderlo kill -CONT $(pgrep set-lang.sh). In questo modo puoi metterlo in pausa, cambiare le lingue normalmente e quindi riprendere.
Sergiy Kolodyazhnyy,

Una rapida idea che ho avuto è che forse usare una scorciatoia da tastiera per i due comandi potrebbe essere il modo di farlo, ma non l'ho ancora testato, solo una teoria finora. Proverò domani quando avrò abbastanza sonno e
riferirò

1
+1 per l'ottimo e approfondito lavoro! Due piccole cose che vorrei menzionare: gli eseguibili ~/binnon hanno bisogno del percorso (né dell'estensione, poiché si trova $PATHdopo un nuovo accesso, vedere: lintian.debian.org/tags/script-with-language-extension .html ) e puoi combinare stop / start in un .desktopfile; in una lista rapida o in una funzione di attivazione / disattivazione. sembra abbastanza perfetto per me.
Jacob Vlijm,

1

Puoi installarlo gxneureseguendo

sudo apt-get install gxneur

Questo software può cambiare automaticamente layout, ma non è perfetto.

Ma ha strumenti molto carini per impostare interruttori di layout manuali.

Puoi fare esattamente quello che vuoi. Per impostare layout specifici per applicazioni specifiche.


0

Lo script seguente è una versione modificata di questo , che è stato pubblicato come soluzione simile per una singola applicazione ( gnome-terminal) qualche tempo fa.

Lo script è stato parzialmente riscritto per questa domanda, per poterlo utilizzare per impostare automaticamente le lingue per più applicazioni.

Come usare in pratica; ricorda automaticamente la lingua impostata per applicazione

Se lo script viene avviato per la prima volta, la lingua corrente si presume essere la lingua predefinita, che è ricordato in un file nascosto: ~/.lang_set.

Quindi l'uso è semplice: se corri ad es. geditNella maggior parte delle finestre e imposti una lingua diversa, quella lingua viene automaticamente connessa geditda quel momento in poi, fino a quando non cambi di nuovo la lingua con geditin primo piano.

Il numero di lingue / applicazioni specifiche è in linea di principio illimitato; basta eseguire l'applicazione e impostare la lingua con la finestra dell'applicazione in primo piano. L'applicazione verrà automaticamente impostata e ricordata senza modificare il codice.

Evento guidato?

Sebbene lo script venga eseguito in un ciclo, il consumo di risorse è minimo. Event driven significherebbe che l' evento è un cambiamento nella finestra in primo piano. Non vedo altra opzione se non quella di "spiare" per la maggior parte della finestra se non quella di fare il check in loop.

Il copione

#!/usr/bin/env python3
import subprocess
import os
import time

key = [
    "org.gnome.desktop.input-sources",
    "gsettings get ", "gsettings set ",
    " sources", " current",
    ]

prev = os.environ["HOME"]+"/.lang_set"

def get(cmd):
    return subprocess.check_output(["/bin/bash", "-c", cmd]).decode("utf-8")

def get_front():
    # produce the frontmost application
    try:
        focus = str(hex(int(get("xdotool getwindowfocus").strip())))
        front = focus[:2]+"0"+focus[2:]
        cmd = "wmctrl -lp"
        w_list = subprocess.check_output(["/bin/bash", "-c",cmd]).decode("utf-8")
        w_match = [w for w in w_list.splitlines() if front in w][0].split()[2]
        application = get("ps -p "+w_match+" -o comm=").strip()
        # fix for 15.04, where the process name of gnome-terminal varies
        application = "gnome-terminal" if "gnome-terminal" in application else application
        return application
    except subprocess.CalledProcessError:
        return None

def get_lang():
    # get the currently running language (output = string)
    curr_n = int(get(key[1]+key[0]+key[4]).strip().split()[-1])
    return str(eval(get(key[1]+key[0]+key[3]))[curr_n])

def read_prev(application):
    # reads the possibly set languages for general and specific use (list)
    if not os.path.exists(prev):
        currlang = get_lang()
        open(prev, "wt").write("default "+currlang+"\n"+application+" "+currlang)
        return [currlang, currlang]
    else:
        return [l.strip() for l in open(prev).readlines()]

def write_changed(application, lang):
    changelist = read_prev(front_2)
    try:
        match = changelist.index([l for l in changelist if application in l][0])
        changelist[match] = application+" "+lang+"\n"
    except IndexError:
        changelist.append(application+" "+lang+"\n")
    open(prev, "wt").write(("\n").join(changelist))

def set_lang(lang):
    # set the currently used language (input = string)
    lang_i = eval(get(key[1]+key[0]+key[3])).index(eval(lang))  
    cmd = key[2]+key[0]+key[4]+" "+str(lang_i)
    subprocess.Popen(["/bin/bash", "-c", cmd])

front_1 = get_front(); lang_1 = get_lang()

while True:
    time.sleep(1)
    front_2 = get_front(); lang_2 = get_lang()
    if front_2 != None:
        if front_2 != front_1:
            try:
                setlist = read_prev(front_2)
                match = [l for l in setlist if front_2 in l][0]
            except IndexError:
                match = [l for l in setlist if "default" in l][0]
                set_lang(match[match.find(" ")+1:])            
        elif lang_2 != lang_1:
            write_changed(front_2, lang_2)
    front_1 = front_2; lang_1 = lang_2

Come impostare

  1. Lo script utilizza sia xdotoole wmctrl:

    sudo apt-get install wmctrl xdotool
    
  2. Copia lo script sopra in un file vuoto, salvalo come set_language.py

  3. Test-eseguirlo con il comando:

    python3 /path/to/set_language.py
    
  4. Se tutto funziona come previsto, aggiungilo alle applicazioni di avvio: Aggiungi alle applicazioni di avvio: Dash> Applicazioni di avvio> Aggiungi. Aggiungi il comando:

    python3 /path/to/set_language.py
    

Taglia unica! +1
Fabby

Hey grazie molto per questo, voglio guardare dentro presto e ti faccio sapere come mi sento su di esso :)
grongor
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.