Python / Tkinter: ¿Usar Tkinter para lenguajes RTL (de derecha a izquierda) como el árabe / hebreo?

¿Es posible utilizar Tkinter para representar interfaces de usuario para idiomas RTL como el árabe o el hebreo? Intenté googlear en “tkinter rtl” y los resultados de búsqueda fueron decepcionantes. El wiki de Tk indica que no hay soporte bidi en este momento.

¿Alguien está desarrollando aplicaciones Tkinter para entornos árabes o hebreos?

Me doy cuenta de que esta es una pregunta antigua, pero empecé a trabajar con Tkinter ayer para desarrollar una aplicación en hebreo en Python. De derecha a izquierda (bidi) no está disponible como parte del marco, pero después de un poco de búsqueda en Google y un poco de investigación, logré falsificarlo convincentemente mediante combinaciones de teclas y reposicionando el cursor a la fuerza. El widget de Mi entrada mantiene la justificación a la izquierda, por lo que el texto hebreo se encuentra aproximadamente en la misma posición que el inglés en el mismo cuadro, pero este enfoque podría modificarse fácilmente para un cuadro con justificación a la derecha. (O, la justificación correcta puede hacer esto más simple). Sin embargo, esto es lo que hice.

Esencialmente, lo que estás haciendo aquí es imponer manualmente la posición del cursor mediante devoluciones de llamada, códigos de caracteres y constantes de índice. Además, debe tener en cuenta las teclas de flecha (las mías se comportan como si se movieran en la dirección que apuntan. Siempre he odiado cómo RTL generalmente invierte las flechas. Sin embargo, esto se puede cambiar fácilmente, si lo prefiere). Retroceso y Supr. Además, hay que provocar algún reposicionamiento manual. Por supuesto, también, si está siguiendo el cursor manualmente, debe actualizar su variable de seguimiento en caso de que el usuario la coloque con el mouse. A continuación se encuentra mi código, con la excepción de que el uso de un global aquí está destinado a eliminar un poco de complejidad de la explicación.

# Here, the necessary bindings. We're going to # have to make modifications on key press, release, # and on a completed mouse click. entryWidget.bind("", rtlPress) entryWidget.bind("", rtlRelease) entryWidget.bind("", rtlMouse) 

A continuación, las tres funciones de callback, que hacen todo nuestro cursor de seguimiento y reubicación.

 #With the following functions, keep in mind that we only want the cursor to move RIGHT #(increase in index) in response to a right arrow press or a DEL. Essentially, we are #compensating for any movement but these explicit conditions. Since the indexing of the #cursor position is LTR, holding it in its current position #while we append more text is #tantamount to moving it right. #On key release, if an arrow key has been invoked, we update our tracking variable to #reflect the new cursor position. If any other key was pressed, we snap the cursor back #to where it was prior to the keypress to prevent it from moving right and cause the #next letter to be appended on the left side of the previous letter. def rtlRelease(event): global hebCursorPos if event.keycode==114 or event.keycode==113: hebCursorPos=event.widget.index(INSERT) else: event.widget.icursor(hebCursorPos) print(str(event.keycode)+" "+str(hebCursorPos)) #On keypress, we must compensate for the natural LTR behavior of backspace(22) and #del(119) def rtlPress(event): global hebCursorPos #In LTR text entry, a backspace naturally removes the character to the left of #the cursor. if event.keycode==22: length = len(event.widget.get()) #In RTL, the right edge is the beginning of the string, so backspace #should do nothing. #If we're at the right edge of the string, we insert a meaningless #character to be deleted so that it appears to the user as if we have #done nothing. if hebCursorPos==length: event.widget.insert(hebCursorPos, " ") #In order to cause the backspace to delete the character to the right #rather than the left of the cursor from the user's perspective, we step #the cursor forward one. This will cause the backspace to delete the #character to the left of the new cursor position, which will be the #character that was to the right of the cursor from the user's #perspective. If we were at the right end of the line, we insert a space #and delete it milliseconds later. We do not need to update the cursor's #position, in the tracking variable, because after the character is #deleted, it is back at the index from which it started, counting index #from an LTR perspective. event.widget.icursor(hebCursorPos+1) else: #Del is more of the same. It deletes the character to the right of the #cursor, but we want it to delete the character to the right. if event.keycode==119: #If we're at the left edge of the string, insert a meaningless character #for the del to delete, so that from the user's perspective it does #nothing. if hebCursorPos==0: event.widget.insert(hebCursorPos, " ") #Otherwise, we will be stepping the cursor one to the left, so #that when it deletes the character to its new right, it will be #deleting the character from what the user thinks is its left. #Because we are deleting a character from the left of the cursor #from the user's perspective, there will be fewer characters to #the left of the cursor once the operation is complete. As #cursor positioning is tracked as an LTR index, we must update #our tracking variable. else: hebCursorPos-=1 #Now, we snap our cursor to the position of our tracking variable. #Either we are preventing it from drifting right due to overlapping #keypresses, or we are repositioning it to maintain the correct index #after a del. event.widget.icursor(hebCursorPos) #Simply put, if the user repositions the cursor with the mouse, track it. def rtlMouse(event): global hebCursorPos hebCursorPos=event.widget.index(INSERT) 

¡Espero que esto ayude! Dado que se logra mediante el movimiento forzado del cursor, hay una ligera fluctuación visual del cursor durante la escritura, pero el orden del texto parece ser correcto, y el cursor parece indicar siempre la posición correcta cuando el usuario no está presionando el botón central. Sin embargo, no estoy haciendo ninguna afirmación de la perfección del código!

Esto quizás tampoco resuelva todo el problema, pero puede resolver el problema de la pantalla, que veo el problema principal.

Básicamente, necesitará dos cosas para revertir el orden de los caracteres y para permitir que se unan, utilicé este reformador , funcionó bien con palabras sencillas sin الحركات diacríticos, pero en algunos casos sigue teniendo errores.

Intente configurar la entrada u otro elemento como “jameel noori nastaleeq” o cualquier otra fuente en urdu