I18N_Arabic

# Source for file WordTag.php

Documentation is available at WordTag.php

1. <?php
2. /**
3. * ----------------------------------------------------------------------
4. *
5. * Copyright (c) 2006-2016 Khaled Al-Sham'aa.
6. *
7. * http://www.ar-php.org
8. *
9. * PHP Version 5
10. *
11. * ----------------------------------------------------------------------
12. *
13. * LICENSE
14. *
15. * This program is open source product; you can redistribute it and/or
16. * modify it under the terms of the GNU Lesser General Public License (LGPL)
17. * as published by the Free Software Foundation; either version 3
18. * of the License, or (at your option) any later version.
19. *
20. * This program is distributed in the hope that it will be useful,
21. * but WITHOUT ANY WARRANTY; without even the implied warranty of
22. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23. * GNU Lesser General Public License for more details.
24. *
25. * You should have received a copy of the GNU Lesser General Public License
26. * along with this program. If not, see <http://www.gnu.org/licenses/lgpl.txt>.
27. *
28. * ----------------------------------------------------------------------
29. *
30. * Class Name: Tagging Arabic Word Class
31. *
32. * Filename: WordTag.php
33. *
34. * Original Author(s): Khaled Al-Sham'aa <khaled@ar-php.org>
35. *
36. * Purpose: Arabic grammarians describe Arabic as being derived from
37. * three main categories: noun, verb and particle. This class
38. * built to recognize the class of a given Arabic word.
39. *
40. * ----------------------------------------------------------------------
41. *
42. * Tagging Arabic Word
43. *
44. * This PHP Class can identifying names, places, dates, and other noun
45. * words and phrases in Arabic language that establish the meaning of a body
46. * of text.
47. *
48. * This process of identifying names, places, dates, and other noun words and
49. * phrases that establish the meaning of a body of text-is critical to software
50. * systems that process large amounts of unstructured data coming from sources such
51. * as email, document files, and the Web.
52. *
53. * Arabic words are classifies into three main classes, namely, verb, noun and
54. * particle. Verbs are sub classified into three subclasses (Past verbs, Present
55. * Verbs, etc.); nouns into forty six subclasses (e.g. Active participle, Passive
56. * participle, Exaggeration pattern, Adjectival noun, Adverbial noun, Infinitive
57. * noun, Common noun, Pronoun, Quantifier, etc.) and particles into twenty three
58. * subclasses (e.g. additional, resumption, Indefinite, Conditional, Conformational,
59. * Prohibition, Imperative, Optative, Reasonal, Dubious, etc.), and from these three
60. * main classes that the rest of the language is derived.
61. *
62. * The most important aspect of this system of describing Arabic is that all the
63. * subclasses of these three main classes inherit properties from the parent
64. * classes.
65. *
66. * Arabic is very rich in categorising words, and contains classes for almost every
67. * form of word imaginable. For example, there are classes for nouns of instruments,
68. * nouns of place and time, nouns of activity and so on. If we tried to use all the
69. * subclasses described by Arabic grammarians, the size of the tagset would soon
70. * reach more than two or three hundred tags. For this reason, we have chosen only
71. * the main classes. But because of the way all the classes inherit from others, it
72. * would be quite simple to extend this tagset to include more subclasses.
73. *
74. * Example:
75. * <code>
76. * include('./I18N/Arabic.php');
77. * $obj = new I18N_Arabic('WordTag');
78. *
79. * $hStr=$obj->highlightText($str,'#80B020');
80. *
81. * echo $str . '<hr />' . $hStr . '<hr />';
82. *
83. * $taggedText = $obj->tagText($str);
84. *
85. * foreach($taggedText as $wordTag) {
86. * list($word, $tag) = $wordTag;
87. *
88. * if ($tag == 1) {
89. * echo "<font color=#DBEC21>$word is Noun</font>, ";
90. * }
91. *
92. * if ($tag == 0) {
93. * echo "$word is not Noun, ";
94. * }
95. * }
96. * </code>
97. *
98. * @category I18N
99. * @package I18N_Arabic
100. * @author Khaled Al-Sham'aa <khaled@ar-php.org>
101. * @copyright 2006-2016 Khaled Al-Sham'aa
102. *
103. * @license LGPL <http://www.gnu.org/licenses/lgpl.txt>
104. * @link http://www.ar-php.org
105. */
107. /**
108. * This PHP class to tagging Arabic Word
109. *
110. * @category I18N
111. * @package I18N_Arabic
112. * @author Khaled Al-Sham'aa <khaled@ar-php.org>
113. * @copyright 2006-2016 Khaled Al-Sham'aa
114. *
115. * @license LGPL <http://www.gnu.org/licenses/lgpl.txt>
116. * @link http://www.ar-php.org
117. */
118. class I18N_Arabic_WordTag
119. {
120. private static $_particlePreNouns = array('عن', 'في', 'مذ', 'منذ',
121. 'من', 'الى', 'على', 'حتى',
122. 'الا', 'غير', 'سوى', 'خلا',
123. 'عدا', 'حاشا', 'ليس');
125. private static $_normalizeAlef = array('أ','إ','آ');
126. private static $_normalizeDiacritics = array('َ','ً','ُ','ٌ',
127. 'ِ','ٍ','ْ','ّ');
129. private $_commonWords = array();
131. /**
132. * Loads initialize values
133. *
134. * @ignore
135. */
136. public function __construct()
137. {
138. $words = file(dirname(__FILE__).'/data/ar-stopwords.txt');
139. $words = array_map('trim', $words);
141. $this->_commonWords = $words;
142. }
144. /**
145. * Check if given rabic word is noun or not
146. *
147. * @param string $word Word you want to check if it is
148. * noun (utf-8)
149. * @param string $word_befor The word before word you want to check
150. *
151. * @return boolean TRUE if given word is Arabic noun
152. * @author Khaled Al-Sham'aa <khaled@ar-php.org>
153. */
154. public static function isNoun($word, $word_befor)
155. {
156. $word = trim($word);
157. $word_befor = trim($word_befor);
159. $word = str_replace(self::$_normalizeAlef, 'ا', $word);
160. $word_befor = str_replace(self::$_normalizeAlef, 'ا', $word_befor);
161. $wordLen = strlen($word);
163. // إذا سبق بحرف جر فهو اسم مجرور
164. if (in_array($word_befor, self::$_particlePreNouns)) {
165. return true;
166. }
168. // إذا سبق بعدد فهو معدود
169. if (is_numeric($word) || is_numeric($word_befor)) {
170. return true;
171. }
173. // إذا كان منون
174. if (mb_substr($word, -1, 1) == 'ً' || mb_substr($word, -1, 1) == 'ٌ'
175. || mb_substr($word, -1, 1) == 'ٍ'
176. ) {
177. return true;
178. }
180. $word = str_replace(self::$_normalizeDiacritics, '', $word);
181. $wordLen = mb_strlen($word);
183. // إن كان معرف بأل التعريف
184. if (mb_substr($word, 0, 1) == 'ا' && mb_substr($word, 1, 1) == 'ل'
185. && $wordLen >= 5
186. ) {
187. return true;
188. }
190. // إذا كان في الكلمة ثلاث ألفات
191. // إن لم تكن الألف الثالثة متطرفة
192. if (mb_substr_count($word, 'ا') >= 3) {
193. return true;
194. }
196. //إن كان مؤنث تأنيث لفظي، منتهي بتاء مربوطة
197. // أو همزة أو ألف مقصورة
198. if ((mb_substr($word, -1, 1) == 'ة' || mb_substr($word, -1, 1) == 'ء'
199. || mb_substr($word, -1, 1) == 'ى') && $wordLen >= 4
200. ) {
201. return true;
202. }
204. // مؤنث تأنيث لفظي،
205. // منتهي بألف وتاء مفتوحة - جمع مؤنث سالم
206. if (mb_substr($word, -1, 1) == 'ت' && mb_substr($word, -2, 1) == 'ا'
207. && $wordLen >= 5
208. ) {
209. return true;
210. }
212. // started by Noon, before REH or LAM, or Noon, is a verb and not a noun
213. if (mb_substr($word, 0, 1) == 'ن' && (mb_substr($word, 1, 1) == 'ر'
214. || mb_substr($word, 1, 1) == 'ل' || mb_substr($word, 1, 1) == 'ن')
215. && $wordLen > 3
216. ) {
217. return false;
218. }
220. // started by YEH, before some letters is a verb and not a noun
221. // YEH,THAL,JEEM,HAH,KHAH,ZAIN,SHEEN,SAD,DAD,TAH,ZAH,GHAIN,KAF
222. $haystack = 'يذجهخزشصضطظغك';
223. if (mb_substr($word, 0, 1) == 'ي'
224. && (mb_strpos($haystack, mb_substr($word, 1, 1)) !== false)
225. && $wordLen > 3
226. ) {
227. return false;
228. }
230. // started by beh or meem, before BEH,FEH,MEEM is a noun and not a verb
231. if ((mb_substr($word, 0, 1) == 'ب' || mb_substr($word, 0, 1) == 'م')
232. && (mb_substr($word, 1, 1) == 'ب' || mb_substr($word, 1, 1) == 'ف'
233. || mb_substr($word, 1, 1) == 'م') && $wordLen > 3
234. ) {
235. return true;
236. }
238. // الكلمات التي تنتهي بياء ونون
239. // أو ألف ونون أو ياء ونون
240. // تكون أسماء ما لم تبدأ بأحد حروف المضارعة
241. if (preg_match('/^[^ايتن]\S{2}[اوي]ن$/u', $word)) {
242. return true;
243. }
245. // إن كان على وزن اسم الآلة
246. // أو اسم المكان أو اسم الزمان
247. if (preg_match('/^م\S{3}$/u', $word)
248. || preg_match('/^م\S{2}ا\S$/u', $word)
249. || preg_match('/^م\S{3}ة$/u', $word)
250. || preg_match('/^\S{2}ا\S$/u', $word)
251. || preg_match('/^\Sا\Sو\S$/u', $word)
252. || preg_match('/^\S{2}و\S$/u', $word)
253. || preg_match('/^\S{2}ي\S$/u', $word)
254. || preg_match('/^م\S{2}و\S$/u', $word)
255. || preg_match('/^م\S{2}ي\S$/u', $word)
256. || preg_match('/^\S{3}ة$/u', $word)
257. || preg_match('/^\S{2}ا\Sة$/u', $word)
258. || preg_match('/^\Sا\S{2}ة$/u', $word)
259. || preg_match('/^\Sا\Sو\Sة$/u', $word)
260. || preg_match('/^ا\S{2}و\Sة$/u', $word)
261. || preg_match('/^ا\S{2}ي\S$/u', $word)
262. || preg_match('/^ا\S{3}$/u', $word)
263. || preg_match('/^\S{3}ى$/u', $word)
264. || preg_match('/^\S{3}اء$/u', $word)
265. || preg_match('/^\S{3}ان$/u', $word)
266. || preg_match('/^م\Sا\S{2}$/u', $word)
267. || preg_match('/^من\S{3}$/u', $word)
268. || preg_match('/^مت\S{3}$/u', $word)
269. || preg_match('/^مست\S{3}$/u', $word)
270. || preg_match('/^م\Sت\S{2}$/u', $word)
271. || preg_match('/^مت\Sا\S{2}$/u', $word)
272. || preg_match('/^\Sا\S{2}$/u', $word)
273. ) {
274. return true;
275. }
277. return false;
278. }
280. /**
281. * Tag all words in a given Arabic string if they are nouns or not
282. *
283. * @param string $str Arabic string you want to tag all its words
284. *
285. * @return array Two dimension array where item[i][0] represent the word i
286. * in the given string, and item[i][1] is 1 if that word is
287. * noun and 0 if it is not
288. * @author Khaled Al-Sham'aa <khaled@ar-php.org>
289. */
290. public static function tagText($str)
291. {
292. $text = array();
293. $words = explode(' ', $str);
294. $prevWord = '';
296. foreach ($words as $word) {
297. if ($word == '') {
298. continue;
299. }
301. if (self::isNoun($word, $prevWord)) {
302. $text[] = array($word, 1);
303. } else {
304. $text[] = array($word, 0);
305. }
307. $prevWord = $word;
308. }
310. return $text;
311. }
313. /**
314. * Highlighted all nouns in a given Arabic string
315. *
316. * @param string $str Arabic string you want to highlighted
317. * all its nouns
318. * @param string $style Name of the CSS class you would like to apply
319. *
320. * @return string Arabic string in HTML format where all nouns highlighted
321. * @author Khaled Al-Sham'aa <khaled@ar-php.org>
322. */
323. public static function highlightText($str, $style = null)
324. {
325. $html = '';
326. $prevTag = 0;
327. $prevWord = '';
329. $taggedText = self::tagText($str);
331. foreach ($taggedText as $wordTag) {
332. list($word, $tag) = $wordTag;
334. if ($prevTag == 1) {
335. if (in_array($word, self::$_particlePreNouns)) {
336. $prevWord = $word;
337. continue;
338. }
340. if ($tag == 0) {
341. $html .= "</span> \r\n";
342. }
343. } else {
344. // if ($tag == 1 && !in_array($word, $this->_commonWords)) {
345. if ($tag == 1) {
346. $html .= " \r\n<span class=\"" . $style ."\">";
347. }
348. }
350. $html .= ' ' . $prevWord . ' ' . $word;
352. if ($prevWord != '') {
353. $prevWord = '';
354. }
355. $prevTag = $tag;
356. }
358. if ($prevTag == 1) {
359. $html .= "</span> \r\n";
360. }
362. return $html;
363. }
364. }

Documentation generated on Fri, 01 Jan 2016 10:26:31 +0200 by phpDocumentor 1.4.0