You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@answer.apache.org by li...@apache.org on 2026/02/05 08:17:41 UTC

(answer) branch dev updated (a6bfd402 -> 638fb082)

This is an automated email from the ASF dual-hosted git repository.

linkinstar pushed a change to branch dev
in repository https://gitbox.apache.org/repos/asf/answer.git


    from a6bfd402 fix: update AI provider configuration ID in default settings
     add fca80abb fix: correct variable name in JSON unmarshal for site general information
     new 638fb082 fix: enhance bracket handling in formatting and add concurrency test for internationalization

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 internal/migrations/v30.go |  2 +-
 pkg/day/day.go             | 21 +++++++++++--
 pkg/day/day_test.go        | 78 +++++++++++++++++++++++++++++++++++++++++++---
 3 files changed, 93 insertions(+), 8 deletions(-)


(answer) 01/01: fix: enhance bracket handling in formatting and add concurrency test for internationalization

Posted by li...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

linkinstar pushed a commit to branch dev
in repository https://gitbox.apache.org/repos/asf/answer.git

commit 638fb082c56431397a3c63d00f3fc57c6b57f08d
Author: LinkinStars <li...@foxmail.com>
AuthorDate: Thu Feb 5 16:17:32 2026 +0800

    fix: enhance bracket handling in formatting and add concurrency test for internationalization
---
 pkg/day/day.go      | 21 +++++++++++++--
 pkg/day/day_test.go | 78 +++++++++++++++++++++++++++++++++++++++++++++++++----
 2 files changed, 92 insertions(+), 7 deletions(-)

diff --git a/pkg/day/day.go b/pkg/day/day.go
index 2fd86a6c..797da68b 100644
--- a/pkg/day/day.go
+++ b/pkg/day/day.go
@@ -174,13 +174,30 @@ func nextStdChunk(from []rune) (to, suffix []rune) {
 	case "a":
 		old = "a"
 	case "[":
-		if len(from) >= 4 && string(from[:4]) == "[at]" {
-			old = "[at]"
+		// treat anything inside [] as literal text, e.g. [at], [a las], [o]
+		end := -1
+		for i := 1; i < len(from); i++ {
+			if from[i] == ']' {
+				end = i
+				break
+			}
+		}
+		if end != -1 {
+			to = []rune(string(from[1:end]))
+			suffix = from[end+1:]
+			return
 		}
+		// no closing bracket, fall back to literal "["
+		old = "["
 	default:
 		old = s
 	}
 
+	if old == "" {
+		// safety: always consume at least one rune
+		old = s
+	}
+
 	tos, ok := placeholder[old]
 	if !ok {
 		to = []rune(old)
diff --git a/pkg/day/day_test.go b/pkg/day/day_test.go
index 4f945d88..1ff75766 100644
--- a/pkg/day/day_test.go
+++ b/pkg/day/day_test.go
@@ -20,17 +20,85 @@
 package day
 
 import (
+	"os"
+	"path/filepath"
+	"runtime"
 	"testing"
 	"time"
 
 	"github.com/stretchr/testify/assert"
+	"gopkg.in/yaml.v3"
 )
 
 func TestFormat(t *testing.T) {
-	sec := time.Now().Unix()
-	tz := "Asia/Shanghai"
-	actual := Format(sec, "YYYY-MM-DD HH:mm:ss", tz)
-	_, _ = time.LoadLocation(tz)
-	expected := time.Unix(sec, 0).Format("2006-01-02 15:04:05")
+	sec := int64(1700000000)
+	tz := "UTC"
+
+	actual := Format(sec, "MMM D, YYYY [a las] HH:mm", tz)
+	expected := time.Unix(sec, 0).Format("Jan 2, 2006") + " a las " + time.Unix(sec, 0).Format("15:04")
 	assert.Equal(t, expected, actual)
 }
+
+func TestFormat_AllLanguagesNoHang(t *testing.T) {
+	_, currentFile, _, ok := runtime.Caller(0)
+	if !ok {
+		t.Fatalf("unable to determine test file path")
+	}
+	i18nDir := filepath.Clean(filepath.Join(filepath.Dir(currentFile), "..", "..", "i18n"))
+	entries, err := os.ReadDir(i18nDir)
+	if err != nil {
+		t.Fatalf("read i18n dir: %v", err)
+	}
+
+	type datesConfig struct {
+		LongDate         string `yaml:"long_date"`
+		LongDateWithYear string `yaml:"long_date_with_year"`
+		LongDateWithTime string `yaml:"long_date_with_time"`
+	}
+	type uiConfig struct {
+		Dates datesConfig `yaml:"dates"`
+	}
+	type fileConfig struct {
+		UI uiConfig `yaml:"ui"`
+	}
+
+	sec := int64(1700000000)
+	tz := "UTC"
+
+	for _, entry := range entries {
+		name := entry.Name()
+		if entry.IsDir() || filepath.Ext(name) != ".yaml" || name == "i18n.yaml" {
+			continue
+		}
+		data, err := os.ReadFile(filepath.Join(i18nDir, name))
+		if err != nil {
+			t.Fatalf("read %s: %v", name, err)
+		}
+		var cfg fileConfig
+		if err := yaml.Unmarshal(data, &cfg); err != nil {
+			t.Fatalf("parse %s: %v", name, err)
+		}
+
+		formats := []string{
+			cfg.UI.Dates.LongDate,
+			cfg.UI.Dates.LongDateWithYear,
+			cfg.UI.Dates.LongDateWithTime,
+		}
+		for _, format := range formats {
+			if format == "" {
+				continue
+			}
+			done := make(chan struct{})
+			go func(f string) {
+				_ = Format(sec, f, tz)
+				close(done)
+			}(format)
+
+			select {
+			case <-done:
+			case <-time.After(200 * time.Millisecond):
+				t.Fatalf("format hang in %s: %q", name, format)
+			}
+		}
+	}
+}