-
-
Notifications
You must be signed in to change notification settings - Fork 648
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix Arabic Selection Option #1236
base: main
Are you sure you want to change the base?
Changes from 6 commits
1bea99d
d30ef26
eb054d8
0c3c071
33508d4
42c33e2
697b117
f3a0a52
24479c8
8e96e60
f4c2956
975e8ad
6665089
2a5e38e
422a341
ed4a307
cf08f49
fa515e1
b265097
2c1226f
31108ef
c811aed
a0f2f2e
8756c8c
33810e2
4d97357
47a2b93
dadb561
02e3b55
73ab727
8d23d0d
d65f76f
c92f7b1
eb21600
03774f5
c628caf
8e32a86
2defc58
319ab80
b87e902
d762c41
d7cf868
b033467
850e562
6473523
e65a179
1653f56
22a2903
a99fcbf
300c424
6e37e27
fc0cdaf
951b64a
f04f073
0eb592a
6220200
9e68a53
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,142 @@ | ||
package letteravatar | ||
|
||
import ( | ||
"embed" | ||
"image" | ||
"image/color" | ||
"image/draw" | ||
"math" | ||
"strings" | ||
"unicode" | ||
|
||
"github.com/golang/freetype" | ||
"github.com/golang/freetype/truetype" | ||
"golang.org/x/image/font" | ||
) | ||
|
||
//go:embed fonts | ||
var fonts embed.FS | ||
|
||
// Options contains the options for letter avatar generation | ||
type Options struct { | ||
PaletteKey string | ||
} | ||
|
||
// Extract returns the first letter of each word in the given name | ||
func Extract(name string) string { | ||
if name == "" { | ||
return "?" | ||
} | ||
|
||
words := strings.Fields(name) | ||
if len(words) == 0 { | ||
return "?" | ||
} | ||
|
||
firstWord := []rune(words[0]) | ||
if len(firstWord) == 0 { | ||
return "?" | ||
} | ||
|
||
firstLetter := string(firstWord[0]) | ||
return firstLetter | ||
} | ||
|
||
// Draw generates a letter avatar image with the given size and text | ||
func Draw(size int, text string, opts *Options) (image.Image, error) { | ||
// Create a new RGBA image | ||
img := image.NewRGBA(image.Rect(0, 0, size, size)) | ||
|
||
// Generate a background color based on the text | ||
bg := generateColor(text, opts.PaletteKey) | ||
|
||
// Draw the background | ||
draw.Draw(img, img.Bounds(), &image.Uniform{bg}, image.Point{}, draw.Src) | ||
|
||
// Load the font | ||
fontBytes, err := fonts.ReadFile("fonts/IBMPlexSansArabic-Regular.ttf") | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
f, err := truetype.Parse(fontBytes) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
// Calculate font size (40% of image size) | ||
fontSize := float64(size) * 0.4 | ||
|
||
// Create a new context for drawing text | ||
c := freetype.NewContext() | ||
c.SetDPI(72) | ||
c.SetFont(f) | ||
c.SetFontSize(fontSize) | ||
c.SetClip(img.Bounds()) | ||
c.SetDst(img) | ||
c.SetSrc(image.White) | ||
c.SetHinting(font.HintingFull) | ||
|
||
// Get text bounds | ||
bounds, err := c.DrawString(text, freetype.Pt(0, 0)) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
// Calculate text position to center it | ||
textWidth := int(bounds.X.Round()) | ||
textHeight := int(c.PointToFixed(fontSize).Round()) | ||
x := (size - textWidth) / 2 | ||
y := (size + textHeight) / 2 | ||
|
||
// Draw the text | ||
_, err = c.DrawString(text, freetype.Pt(x, y)) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
return img, nil | ||
} | ||
|
||
// generateColor generates a color based on the text | ||
func generateColor(text, key string) color.Color { | ||
// Simple hash function | ||
hash := 0 | ||
for _, r := range text + key { | ||
hash = int(r) + ((hash << 5) - hash) | ||
} | ||
|
||
// Convert hash to color | ||
hue := float64(hash%360) / 360.0 | ||
saturation := 0.5 | ||
value := 0.95 | ||
|
||
// Convert HSV to RGB | ||
h := hue * 6.0 | ||
c := value * saturation | ||
x := c * (1.0 - math.Abs(math.Mod(h, 2.0)-1.0)) | ||
m := value - c | ||
|
||
var r, g, b float64 | ||
switch int(h) { | ||
case 0: | ||
r, g, b = c, x, 0 | ||
case 1: | ||
r, g, b = x, c, 0 | ||
case 2: | ||
r, g, b = 0, c, x | ||
case 3: | ||
r, g, b = 0, x, c | ||
case 4: | ||
r, g, b = x, 0, c | ||
default: | ||
r, g, b = c, 0, x | ||
} | ||
|
||
return color.RGBA{ | ||
R: uint8((r + m) * 255), | ||
G: uint8((g + m) * 255), | ||
B: uint8((b + m) * 255), | ||
A: 255, | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,6 +3,7 @@ | |
"action.change": "تغيير", | ||
"action.close": "إغلاق", | ||
"action.confirm": "تأكيد", | ||
"action.copylink": "نسخ الرابط", | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sorry, we don't manage changes to the localised strings here. Please can you make the changes to the arabic strings here: https://crowdin.com/project/fider Then they can be pulled into the next release Thanks There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sure I will upload an updated version, but I still have some modification on it along with some missing strings |
||
"action.delete": "حذف", | ||
"action.edit": "تحرير", | ||
"action.markallasread": "تحديد الكل كمقروء", | ||
|
@@ -11,20 +12,21 @@ | |
"action.save": "حفظ", | ||
"action.signin": "تسجيل الدخول", | ||
"action.submit": "إرسال", | ||
"email.new_comment.text": "علق على", | ||
"enum.poststatus.completed": "مكتمل", | ||
"enum.poststatus.declined": "مرفوض", | ||
"enum.poststatus.deleted": "محذوف", | ||
"enum.poststatus.duplicate": "مكرر", | ||
"enum.poststatus.open": "مفتوح", | ||
"enum.poststatus.planned": "مخطط له", | ||
"enum.poststatus.started": "بدأ", | ||
"enum.poststatus.started": "بدأ العمل عليه", | ||
"error.expired.text": "الرابط الذي نقرت عليه قد انتهت صلاحيته.", | ||
"error.expired.title": "منتهي الصلاحية", | ||
"error.forbidden.text": "أنت غير مخول لعرض هذه الصفحة.", | ||
"error.forbidden.title": "ممنوع", | ||
"error.internalerror.text": "حدث خطأ ونحن نعمل على إصلاح المشكلة! سنكون في الخدمة قريباً.", | ||
"error.internalerror.title": "عفواً! هذا غير متوقع...", | ||
"error.pagenotfound.text": "الرابط الذي نقرت عليه قد يكون مكسورًا أو قد تكون الصفحة قد تمت إزالتها.", | ||
"error.pagenotfound.text": "الرابط الذي نقرت عليه قد يكون معطوباً أو قد تكون الصفحة قد تمت إزالتها.", | ||
"error.pagenotfound.title": "الصفحة غير موجودة", | ||
"error.unauthorized.text": "أنت غير مخول لعرض هذه الصفحة.", | ||
"error.unauthorized.title": "غير مخول", | ||
|
@@ -59,6 +61,7 @@ | |
"label.none": "لا شيء", | ||
"label.notifications": "إشعارات", | ||
"label.or": "أو", | ||
"label.staff": "مشرف", | ||
"label.subscribe": "اشتراك", | ||
"label.tags": "وسوم", | ||
"label.unread": "غير مقروء", | ||
|
@@ -81,6 +84,9 @@ | |
"modal.deleteaccount.text": "<0>عند اختيارك حذف حسابك، سنمحو جميع معلوماتك الشخصية إلى الأبد. سيبقى المحتوى الذي قمت بنشره، ولكنه سيصبح مجهولًا.</0><1>هذه العملية لا رجعة فيها. <2>هل أنت متأكد؟</2></1>", | ||
"modal.deletecomment.header": "حذف التعليق", | ||
"modal.deletecomment.text": "هذه العملية لا رجعة فيها. <0>هل أنت متأكد؟</0>", | ||
"modal.notifications.nonew": "لا يوجد اشعارات جديدة!", | ||
"modal.notifications.previous": "الإشعارات السابقة", | ||
"modal.notifications.unread": "إشعارات غير مقروءة", | ||
"modal.showvotes.message.zeromatches": "لم يتم العثور على مستخدمين مطابقين لـ <0>{0}</0>.", | ||
"modal.showvotes.query.placeholder": "ابحث عن المستخدمين بالاسم...", | ||
"modal.signin.header": "تسجيل الدخول للمشاركة والتصويت", | ||
|
@@ -121,12 +127,17 @@ | |
"mysettings.notification.title": "استخدم اللوحة التالية لاختيار الأحداث التي ترغب في تلقي إشعارات عنها", | ||
"mysettings.page.subtitle": "إدارة إعدادات ملفك الشخصي", | ||
"mysettings.page.title": "الإعدادات", | ||
"notification.leftcomment": "علق على", | ||
"notification.newpost": "منشور جديد", | ||
"page.backhome": "أعدني إلى <0>{0}</0> الصفحة الرئيسية.", | ||
"page.notinvited.text": "لم نتمكن من العثور على حساب لبريدك الإلكتروني.", | ||
"page.notinvited.title": "غير مدعو", | ||
"page.pendingactivation.text": "لقد أرسلنا لك بريدًا إلكترونيًا يحتوي على رابط لتفعيل حسابك.", | ||
"page.pendingactivation.text2": "يرجى التحقق من بريدك الوارد لتفعيله.", | ||
"page.pendingactivation.title": "حسابك في انتظار التفعيل", | ||
"showpost.comment.copylink.error": "فشل في نسخ رابط التعليق، يرجى نسخ عنوان URL للصفحة", | ||
"showpost.comment.copylink.success": "تم نسخ رابط التعليق إلى الحافظة", | ||
"showpost.comment.unknownhighlighted": "معرف التعليق غير صالح #{id}", | ||
"showpost.commentinput.placeholder": "اترك تعليقاً", | ||
"showpost.discussionpanel.emptymessage": "لم يقم أحد بالتعليق بعد.", | ||
"showpost.label.author": "نشر بواسطة <0/> · <1/>", | ||
|
@@ -149,5 +160,5 @@ | |
"signin.message.onlyadmins": "حاليًا مسموح فقط بتسجيل الدخول إلى حساب مسؤول", | ||
"signin.message.private.text": "إذا كان لديك حساب أو دعوة، يمكنك استخدام الخيارات التالية لتسجيل الدخول.", | ||
"signin.message.private.title": "<0>{0}</0> مساحة خاصة، يجب عليك تسجيل الدخول للمشاركة والتصويت.", | ||
"{count, plural, one {# وسم} other {# وسوم}}": "{count, plural, one {# وسم} other {# وسوم}}" | ||
} | ||
"{count, plural, one {# tag} other {# tags}}": "{count, plural, one {# وسم} other {# وسوم}}" | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks interesting. So you use the font to generate the letter avatar, so that it supports arabic letters. That's cool - if we used this we'd just need to make sure we can support both arabic and non-arabic. Do you have any thoughts about how best to manage that?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I give up and convert the Arabic letters to English,Ex: ب = B , from my very basic experience with php and converting text to image, Arabic language is very challenging