├── README.txt ├── prevalence-serialized-i18n.lisp ├── prevalence-serialized-i18n.asd ├── package.lisp ├── internationalization-stuff.lisp └── license.txt /README.txt: -------------------------------------------------------------------------------- 1 | This is small library used for i18n experiment. 2 | -------------------------------------------------------------------------------- /prevalence-serialized-i18n.lisp: -------------------------------------------------------------------------------- 1 | ;;;; prevalence-serialized-i18n.lisp 2 | 3 | (in-package #:prevalence-serialized-i18n) 4 | 5 | ;;; "prevalence-serialized-i18n" goes here. Hacks and glory await! 6 | 7 | -------------------------------------------------------------------------------- /prevalence-serialized-i18n.asd: -------------------------------------------------------------------------------- 1 | ;;;; prevalence-serialized-i18n.asd 2 | 3 | (asdf:defsystem #:prevalence-serialized-i18n 4 | :serial t 5 | :version "0.1.1" 6 | :description "Strings and their translations serialized with prevalence s-serialize" 7 | :author "Olexiy Zamkoviy " 8 | :license "LLGPL" 9 | :depends-on (#:cl-prevalence #:cl-ppcre #:closer-mop #:weblocks-stores #:weblocks-util #:weblocks-utils) 10 | :components 11 | ((:file "package") 12 | (:file "internationalization-stuff" :depends-on ("package")))) 13 | 14 | -------------------------------------------------------------------------------- /package.lisp: -------------------------------------------------------------------------------- 1 | ;;;; package.lisp 2 | 3 | (defpackage #:prevalence-serialized-i18n 4 | (:use #:cl #:c2mop #:weblocks-stores) 5 | (:export 6 | #:translate #:translation 7 | #:value 8 | #:active 9 | #:*prevalence-serialized-i18n-store*) 10 | (:import-from :weblocks-utils #:first-by-values) 11 | (:shadowing-import-from :c2mop #:defclass #:defgeneric #:defmethod 12 | #:standard-generic-function #:ensure-generic-function 13 | #:standard-class #:typep #:subtypep #:standard-method) 14 | (:shadowing-import-from :weblocks-util #:asdf-system-directory)) 15 | -------------------------------------------------------------------------------- /internationalization-stuff.lisp: -------------------------------------------------------------------------------- 1 | (in-package :prevalence-serialized-i18n) 2 | 3 | (defclass translation () 4 | ((id) 5 | (translation-string 6 | :type string 7 | :initarg :translation-string 8 | :accessor translation-string) 9 | (value :initform nil 10 | :initarg :value 11 | :accessor value) 12 | (scope 13 | :initform nil 14 | :initarg :scope 15 | :accessor translation-scope 16 | :documentation "Translation string scope, contains 17 | :lang key - a language, 18 | :form key - can be :genitive :accusative etc. 19 | :gender key - can be :masculine or :feminine or :neuter 20 | :preceding-gender key - has values same as :gender key 21 | :count key - has values depending on language, 22 | for Russian this is :one :few :many (it has 3 number forms) 23 | for English this is :one :many (it has 2 number forms) 24 | string/word form and other scope options useful for translation.") 25 | (active :initform nil 26 | :initarg :active 27 | :accessor translation-active-p) 28 | (time-created :initform (get-universal-time)) 29 | (time-last-used :initform (get-universal-time))) 30 | (:documentation "Database class, contains translation values for different strings")) 31 | 32 | (defstore *prevalence-serialized-i18n-store* :prevalence 33 | (merge-pathnames 34 | (make-pathname :directory '(:relative "data")) 35 | (asdf-system-directory :prevalence-serialized-i18n))) 36 | 37 | (weblocks-stores:open-stores) 38 | 39 | (defun translation-scopes-equalp (item1 item2) 40 | (unless (= (length item1) (length item2)) 41 | (return-from translation-scopes-equalp nil)) 42 | 43 | (loop for (key value) on item1 by #'cddr do 44 | (unless (equal value (getf item2 key)) 45 | (return-from translation-scopes-equalp nil))) 46 | t) 47 | 48 | ; Useful in cases when russian strings need to be translated 49 | (defvar *yandex-translate-api-key* nil) 50 | (defun translate-with-yandex (str &key (direction "ru-en")) 51 | (unless *yandex-translate-api-key* 52 | (return-from translate-with-yandex str)) 53 | 54 | (let* ((key *yandex-translate-api-key*) 55 | (url (format nil "https://translate.yandex.net/api/v1.5/tr.json/translate?key=~A&lang=~A&text=~A" key direction (arnesi:escape-as-uri str)))) 56 | (second (assoc :text (json:decode-json-from-string 57 | (with-output-to-string (s) 58 | (external-program:run "curl" (list "-s" url) :output s))))))) 59 | 60 | (defun translate (string &rest scope) 61 | (when (zerop (length string)) 62 | (return-from translate string)) 63 | 64 | (let ((found-string (first-by-values 'translation 65 | :store *prevalence-serialized-i18n-store* 66 | :translation-string (cons string #'string=) 67 | :scope (cons scope #'translation-scopes-equalp)))) 68 | (if found-string 69 | (progn 70 | (setf (slot-value found-string 'time-last-used) (get-universal-time)) 71 | (slot-value found-string 'value)) 72 | (progn 73 | (weblocks-stores:persist-object 74 | *prevalence-serialized-i18n-store* 75 | (make-instance 'translation 76 | :translation-string string 77 | :value (if (equal (weblocks::current-locale) :ru) string (translate-with-yandex string)) 78 | :scope scope 79 | :active nil)) 80 | string)))) 81 | -------------------------------------------------------------------------------- /license.txt: -------------------------------------------------------------------------------- 1 | Preamble to the Gnu Lesser General Public License 2 | 3 | Copyright (c) 2000 Franz Incorporated, Berkeley, CA 94704 4 | 5 | The concept of the GNU Lesser General Public License version 2.1 6 | ("LGPL") has been adopted to govern the use and distribution of 7 | above-mentioned application. However, the LGPL uses terminology that 8 | is more appropriate for a program written in C than one written in 9 | Lisp. Nevertheless, the LGPL can still be applied to a Lisp program if 10 | certain clarifications are made. This document details those 11 | clarifications. Accordingly, the license for the open-source Lisp 12 | applications consists of this document plus the LGPL. Wherever there 13 | is a conflict between this document and the LGPL, this document takes 14 | precedence over the LGPL. 15 | 16 | A "Library" in Lisp is a collection of Lisp functions, data and 17 | foreign modules. The form of the Library can be Lisp source code (for 18 | processing by an interpreter) or object code (usually the result of 19 | compilation of source code or built with some other 20 | mechanisms). Foreign modules are object code in a form that can be 21 | linked into a Lisp executable. When we speak of functions we do so in 22 | the most general way to include, in addition, methods and unnamed 23 | functions. Lisp "data" is also a general term that includes the data 24 | structures resulting from defining Lisp classes. A Lisp application 25 | may include the same set of Lisp objects as does a Library, but this 26 | does not mean that the application is necessarily a "work based on the 27 | Library" it contains. 28 | 29 | The Library consists of everything in the distribution file set before 30 | any modifications are made to the files. If any of the functions or 31 | classes in the Library are redefined in other files, then those 32 | redefinitions ARE considered a work based on the Library. If 33 | additional methods are added to generic functions in the Library, 34 | those additional methods are NOT considered a work based on the 35 | Library. If Library classes are subclassed, these subclasses are NOT 36 | considered a work based on the Library. If the Library is modified to 37 | explicitly call other functions that are neither part of Lisp itself 38 | nor an available add-on module to Lisp, then the functions called by 39 | the modified Library ARE considered a work based on the Library. The 40 | goal is to ensure that the Library will compile and run without 41 | getting undefined function errors. 42 | 43 | It is permitted to add proprietary source code to the Library, but it 44 | must be done in a way such that the Library will still run without 45 | that proprietary code present. Section 5 of the LGPL distinguishes 46 | between the case of a library being dynamically linked at runtime and 47 | one being statically linked at build time. Section 5 of the LGPL 48 | states that the former results in an executable that is a "work that 49 | uses the Library." Section 5 of the LGPL states that the latter 50 | results in one that is a "derivative of the Library", which is 51 | therefore covered by the LGPL. Since Lisp only offers one choice, 52 | which is to link the Library into an executable at build time, we 53 | declare that, for the purpose applying the LGPL to the Library, an 54 | executable that results from linking a "work that uses the Library" 55 | with the Library is considered a "work that uses the Library" and is 56 | therefore NOT covered by the LGPL. 57 | 58 | Because of this declaration, section 6 of LGPL is not applicable to 59 | the Library. However, in connection with each distribution of this 60 | executable, you must also deliver, in accordance with the terms and 61 | conditions of the LGPL, the source code of Library (or your derivative 62 | thereof) that is incorporated into this executable. 63 | 64 | GNU LESSER GENERAL PUBLIC LICENSE 65 | Version 3, 29 June 2007 66 | 67 | Copyright (C) 2007 Free Software Foundation, Inc. 68 | Everyone is permitted to copy and distribute verbatim copies 69 | of this license document, but changing it is not allowed. 70 | 71 | 72 | This version of the GNU Lesser General Public License incorporates 73 | the terms and conditions of version 3 of the GNU General Public 74 | License, supplemented by the additional permissions listed below. 75 | 76 | 0. Additional Definitions. 77 | 78 | As used herein, "this License" refers to version 3 of the GNU Lesser 79 | General Public License, and the "GNU GPL" refers to version 3 of the GNU 80 | General Public License. 81 | 82 | "The Library" refers to a covered work governed by this License, 83 | other than an Application or a Combined Work as defined below. 84 | 85 | An "Application" is any work that makes use of an interface provided 86 | by the Library, but which is not otherwise based on the Library. 87 | Defining a subclass of a class defined by the Library is deemed a mode 88 | of using an interface provided by the Library. 89 | 90 | A "Combined Work" is a work produced by combining or linking an 91 | Application with the Library. The particular version of the Library 92 | with which the Combined Work was made is also called the "Linked 93 | Version". 94 | 95 | The "Minimal Corresponding Source" for a Combined Work means the 96 | Corresponding Source for the Combined Work, excluding any source code 97 | for portions of the Combined Work that, considered in isolation, are 98 | based on the Application, and not on the Linked Version. 99 | 100 | The "Corresponding Application Code" for a Combined Work means the 101 | object code and/or source code for the Application, including any data 102 | and utility programs needed for reproducing the Combined Work from the 103 | Application, but excluding the System Libraries of the Combined Work. 104 | 105 | 1. Exception to Section 3 of the GNU GPL. 106 | 107 | You may convey a covered work under sections 3 and 4 of this License 108 | without being bound by section 3 of the GNU GPL. 109 | 110 | 2. Conveying Modified Versions. 111 | 112 | If you modify a copy of the Library, and, in your modifications, a 113 | facility refers to a function or data to be supplied by an Application 114 | that uses the facility (other than as an argument passed when the 115 | facility is invoked), then you may convey a copy of the modified 116 | version: 117 | 118 | a) under this License, provided that you make a good faith effort to 119 | ensure that, in the event an Application does not supply the 120 | function or data, the facility still operates, and performs 121 | whatever part of its purpose remains meaningful, or 122 | 123 | b) under the GNU GPL, with none of the additional permissions of 124 | this License applicable to that copy. 125 | 126 | 3. Object Code Incorporating Material from Library Header Files. 127 | 128 | The object code form of an Application may incorporate material from 129 | a header file that is part of the Library. You may convey such object 130 | code under terms of your choice, provided that, if the incorporated 131 | material is not limited to numerical parameters, data structure 132 | layouts and accessors, or small macros, inline functions and templates 133 | (ten or fewer lines in length), you do both of the following: 134 | 135 | a) Give prominent notice with each copy of the object code that the 136 | Library is used in it and that the Library and its use are 137 | covered by this License. 138 | 139 | b) Accompany the object code with a copy of the GNU GPL and this license 140 | document. 141 | 142 | 4. Combined Works. 143 | 144 | You may convey a Combined Work under terms of your choice that, 145 | taken together, effectively do not restrict modification of the 146 | portions of the Library contained in the Combined Work and reverse 147 | engineering for debugging such modifications, if you also do each of 148 | the following: 149 | 150 | a) Give prominent notice with each copy of the Combined Work that 151 | the Library is used in it and that the Library and its use are 152 | covered by this License. 153 | 154 | b) Accompany the Combined Work with a copy of the GNU GPL and this license 155 | document. 156 | 157 | c) For a Combined Work that displays copyright notices during 158 | execution, include the copyright notice for the Library among 159 | these notices, as well as a reference directing the user to the 160 | copies of the GNU GPL and this license document. 161 | 162 | d) Do one of the following: 163 | 164 | 0) Convey the Minimal Corresponding Source under the terms of this 165 | License, and the Corresponding Application Code in a form 166 | suitable for, and under terms that permit, the user to 167 | recombine or relink the Application with a modified version of 168 | the Linked Version to produce a modified Combined Work, in the 169 | manner specified by section 6 of the GNU GPL for conveying 170 | Corresponding Source. 171 | 172 | 1) Use a suitable shared library mechanism for linking with the 173 | Library. A suitable mechanism is one that (a) uses at run time 174 | a copy of the Library already present on the user's computer 175 | system, and (b) will operate properly with a modified version 176 | of the Library that is interface-compatible with the Linked 177 | Version. 178 | 179 | e) Provide Installation Information, but only if you would otherwise 180 | be required to provide such information under section 6 of the 181 | GNU GPL, and only to the extent that such information is 182 | necessary to install and execute a modified version of the 183 | Combined Work produced by recombining or relinking the 184 | Application with a modified version of the Linked Version. (If 185 | you use option 4d0, the Installation Information must accompany 186 | the Minimal Corresponding Source and Corresponding Application 187 | Code. If you use option 4d1, you must provide the Installation 188 | Information in the manner specified by section 6 of the GNU GPL 189 | for conveying Corresponding Source.) 190 | 191 | 5. Combined Libraries. 192 | 193 | You may place library facilities that are a work based on the 194 | Library side by side in a single library together with other library 195 | facilities that are not Applications and are not covered by this 196 | License, and convey such a combined library under terms of your 197 | choice, if you do both of the following: 198 | 199 | a) Accompany the combined library with a copy of the same work based 200 | on the Library, uncombined with any other library facilities, 201 | conveyed under the terms of this License. 202 | 203 | b) Give prominent notice with the combined library that part of it 204 | is a work based on the Library, and explaining where to find the 205 | accompanying uncombined form of the same work. 206 | 207 | 6. Revised Versions of the GNU Lesser General Public License. 208 | 209 | The Free Software Foundation may publish revised and/or new versions 210 | of the GNU Lesser General Public License from time to time. Such new 211 | versions will be similar in spirit to the present version, but may 212 | differ in detail to address new problems or concerns. 213 | 214 | Each version is given a distinguishing version number. If the 215 | Library as you received it specifies that a certain numbered version 216 | of the GNU Lesser General Public License "or any later version" 217 | applies to it, you have the option of following the terms and 218 | conditions either of that published version or of any later version 219 | published by the Free Software Foundation. If the Library as you 220 | received it does not specify a version number of the GNU Lesser 221 | General Public License, you may choose any version of the GNU Lesser 222 | General Public License ever published by the Free Software Foundation. 223 | 224 | If the Library as you received it specifies that a proxy can decide 225 | whether future versions of the GNU Lesser General Public License shall 226 | apply, that proxy's public statement of acceptance of any version is 227 | permanent authorization for you to choose that version for the 228 | Library. 229 | --------------------------------------------------------------------------------